Bug 789420 - Don't optimize bitwise ops if one of the operands is an object. r=dvander

This commit is contained in:
Jan de Mooij 2012-09-20 08:55:30 +02:00
parent 56bcd082b7
commit ab06fe89b0
5 changed files with 56 additions and 15 deletions

View File

@ -2614,7 +2614,7 @@ IonBuilder::jsop_bitnot()
MBitNot *ins = MBitNot::New(input);
current->add(ins);
ins->infer(oracle->unaryOp(script, pc));
ins->infer(oracle->unaryTypes(script, pc));
current->push(ins);
if (ins->isEffectful() && !resumeAfter(ins))
@ -2660,7 +2660,7 @@ IonBuilder::jsop_bitop(JSOp op)
}
current->add(ins);
ins->infer(oracle->binaryOp(script, pc));
ins->infer(oracle->binaryTypes(script, pc));
current->push(ins);
if (ins->isEffectful() && !resumeAfter(ins))

View File

@ -488,9 +488,9 @@ MCall::addArg(size_t argnum, MPassArg *arg)
}
void
MBitNot::infer(const TypeOracle::Unary &u)
MBitNot::infer(const TypeOracle::UnaryTypes &u)
{
if (u.ival == MIRType_Object)
if (u.inTypes->maybeObject())
specialization_ = MIRType_None;
else
specialization_ = MIRType_Int32;
@ -533,9 +533,9 @@ MBinaryBitwiseInstruction::foldsTo(bool useValueNumbers)
}
void
MBinaryBitwiseInstruction::infer(const TypeOracle::Binary &b)
MBinaryBitwiseInstruction::infer(const TypeOracle::BinaryTypes &b)
{
if (b.lhs == MIRType_Object || b.rhs == MIRType_Object) {
if (b.lhsTypes->maybeObject() || b.rhsTypes->maybeObject()) {
specialization_ = MIRType_None;
} else {
specialization_ = MIRType_Int32;
@ -544,24 +544,24 @@ MBinaryBitwiseInstruction::infer(const TypeOracle::Binary &b)
}
void
MShiftInstruction::infer(const TypeOracle::Binary &b)
MShiftInstruction::infer(const TypeOracle::BinaryTypes &b)
{
if (b.lhs == MIRType_Object || b.rhs == MIRType_Object)
if (b.lhsTypes->maybeObject() || b.rhsTypes->maybeObject())
specialization_ = MIRType_None;
else
specialization_ = MIRType_Int32;
}
void
MUrsh::infer(const TypeOracle::Binary &b)
MUrsh::infer(const TypeOracle::BinaryTypes &b)
{
if (b.lhs == MIRType_Object || b.rhs == MIRType_Object) {
if (b.lhsTypes->maybeObject() || b.rhsTypes->maybeObject()) {
specialization_ = MIRType_None;
setResultType(MIRType_Value);
return;
}
if (b.rval == MIRType_Double) {
if (b.outTypes->getKnownTypeTag() == JSVAL_TYPE_DOUBLE) {
specialization_ = MIRType_Double;
setResultType(MIRType_Double);
return;

View File

@ -1792,7 +1792,7 @@ class MBitNot
}
MDefinition *foldsTo(bool useValueNumbers);
void infer(const TypeOracle::Unary &u);
void infer(const TypeOracle::UnaryTypes &u);
bool congruentTo(MDefinition *const &ins) const {
return congruentIfOperandsEqual(ins);
@ -1888,7 +1888,7 @@ class MBinaryBitwiseInstruction
virtual MDefinition *foldIfZero(size_t operand) = 0;
virtual MDefinition *foldIfNegOne(size_t operand) = 0;
virtual MDefinition *foldIfEqual() = 0;
virtual void infer(const TypeOracle::Binary &b);
virtual void infer(const TypeOracle::BinaryTypes &b);
bool congruentTo(MDefinition *const &ins) const {
return congruentIfOperandsEqual(ins);
@ -1978,7 +1978,7 @@ class MShiftInstruction
MDefinition *foldIfEqual() {
return this;
}
virtual void infer(const TypeOracle::Binary &b);
virtual void infer(const TypeOracle::BinaryTypes &b);
};
class MLsh : public MShiftInstruction
@ -2055,7 +2055,7 @@ class MUrsh : public MShiftInstruction
return this;
}
void infer(const TypeOracle::Binary &b);
void infer(const TypeOracle::BinaryTypes &b);
bool canOverflow() {
// solution is only negative when lhs < 0 and rhs & 0x1f == 0

View File

@ -0,0 +1,38 @@
function g1(x, y) {
return 0 & y;
}
var c1 = 0;
function f1() {
for (var i=0; i<100; i++) {
g1(i, i);
g1(i, {valueOf: function() { c1++; return 0; }});
}
}
f1();
assertEq(c1, 100);
function g2(x, y) {
~y;
}
var c2 = 0;
function f2() {
for (var i=0; i<100; i++) {
g2(i, i);
g2(i, {valueOf: function() { c2++; return 0; }});
}
}
f2();
assertEq(c2, 100);
function g3(x, y) {
return 0 >>> y;
}
var c3 = 0;
function f3() {
for (var i=0; i<100; i++) {
g3(i, i);
g3(i, {valueOf: function() { c3++; return 0; }});
}
}
f3();
assertEq(c3, 100);

View File

@ -493,6 +493,9 @@ class StackTypeSet : public TypeSet
bool isMagicArguments() { return getKnownTypeTag() == JSVAL_TYPE_MAGIC; }
/* Whether this value may be an object. */
bool maybeObject() { return unknownObject() || baseObjectCount() > 0; }
/* Whether the type set contains objects with any of a set of flags. */
bool hasObjectFlags(JSContext *cx, TypeObjectFlags flags);