Bug 925586 - IonMonkey: Document MUrsh's special case exemption from type() rules, and restrict it to only the cases that need it. r=nbp

This commit is contained in:
Dan Gohman 2013-10-15 20:49:44 -07:00
parent 41d9d5c4bf
commit fd8c03c205
7 changed files with 37 additions and 26 deletions

View File

@ -2027,8 +2027,8 @@ class LBitOpI : public LInstructionHelper<1, 2, 0>
{ }
const char *extraName() const {
if (bitop() == JSOP_URSH && mir_->toUrsh()->canOverflow())
return "UrshCanOverflow";
if (bitop() == JSOP_URSH && mir_->toUrsh()->bailoutsDisabled())
return "ursh:BailoutsDisabled";
return js_CodeName[op_];
}

View File

@ -1466,9 +1466,9 @@ MMul::canOverflow()
}
bool
MUrsh::canOverflow()
MUrsh::fallible()
{
if (!canOverflow_)
if (bailoutsDisabled())
return false;
return !range() || !range()->hasInt32Bounds();
}
@ -2013,7 +2013,14 @@ MUrsh::NewAsmJS(MDefinition *left, MDefinition *right)
{
MUrsh *ins = new MUrsh(left, right);
ins->specializeForAsmJS();
ins->canOverflow_ = false;
// Since Ion has no UInt32 type, we use Int32 and we have a special
// exception to the type rules: we can return values in
// (INT32_MIN,UINT32_MAX] and still claim that we have an Int32 type
// without bailing out. This is necessary because Ion has no UInt32
// type and we can't have bailouts in asm.js code.
ins->bailoutsDisabled_ = true;
return ins;
}

View File

@ -558,7 +558,8 @@ class MDefinition : public MNode
bool is##opcode() const { \
return op() == Op_##opcode; \
} \
inline M##opcode *to##opcode();
inline M##opcode *to##opcode(); \
inline const M##opcode *to##opcode() const;
MIR_OPCODE_LIST(OPCODE_CASTS)
# undef OPCODE_CASTS
@ -3242,11 +3243,11 @@ class MRsh : public MShiftInstruction
class MUrsh : public MShiftInstruction
{
bool canOverflow_;
bool bailoutsDisabled_;
MUrsh(MDefinition *left, MDefinition *right)
: MShiftInstruction(left, right),
canOverflow_(true)
bailoutsDisabled_(false)
{ }
public:
@ -3264,12 +3265,12 @@ class MUrsh : public MShiftInstruction
void infer(BaselineInspector *inspector, jsbytecode *pc);
bool canOverflow();
bool fallible() {
return canOverflow();
bool bailoutsDisabled() const {
return bailoutsDisabled_;
}
bool fallible();
void computeRange();
};
@ -8946,6 +8947,11 @@ class MAsmJSCheckOverRecursed : public MNullaryInstruction
{ \
JS_ASSERT(is##opcode()); \
return static_cast<M##opcode *>(this); \
} \
const M##opcode *MDefinition::to##opcode() const \
{ \
JS_ASSERT(is##opcode()); \
return static_cast<const M##opcode *>(this); \
}
MIR_OPCODE_LIST(OPCODE_CASTS)
#undef OPCODE_CASTS

View File

@ -436,6 +436,14 @@ Range::Range(const MDefinition *def)
}
}
// As a special case, MUrsh is permitted to claim a result type of
// MIRType_Int32 while actually returning values in [0,UINT32_MAX] without
// bailouts. If range analysis hasn't ruled out values in
// (INT32_MAX,UINT32_MAX], set the range to be conservatively correct for
// use as either a uint32 or an int32.
if (!hasInt32UpperBound() && def->isUrsh() && def->toUrsh()->bailoutsDisabled())
lower_ = INT32_MIN;
assertInvariants();
}
@ -1072,8 +1080,6 @@ MUrsh::computeRange()
}
JS_ASSERT(range()->lower() >= 0);
if (type() == MIRType_Int32 && !range()->hasInt32UpperBound())
range()->extendUInt32ToInt32Min();
}
void

View File

@ -517,14 +517,6 @@ class Range : public TempObject {
// it to the [0, 1] range. Otherwise do nothing.
void wrapAroundToBoolean();
// As we lack support of MIRType_UInt32, we need to work around the int32
// representation by doing an overflow while keeping the upper infinity to
// repesent the fact that the value might reach bigger numbers.
void extendUInt32ToInt32Min() {
JS_ASSERT(!hasInt32UpperBound());
lower_ = JSVAL_INT_MIN;
}
const SymbolicBound *symbolicLower() const {
return symbolicLower_;
}

View File

@ -907,7 +907,7 @@ CodeGeneratorARM::visitShiftI(LShiftI *ins)
} else {
// x >>> 0 can overflow.
masm.ma_mov(lhs, dest);
if (ins->mir()->toUrsh()->canOverflow()) {
if (ins->mir()->toUrsh()->fallible()) {
masm.ma_cmp(dest, Imm32(0));
if (!bailoutIf(Assembler::LessThan, ins->snapshot()))
return false;
@ -932,7 +932,7 @@ CodeGeneratorARM::visitShiftI(LShiftI *ins)
break;
case JSOP_URSH:
masm.ma_lsr(dest, lhs, dest);
if (ins->mir()->toUrsh()->canOverflow()) {
if (ins->mir()->toUrsh()->fallible()) {
// x >>> 0 can overflow.
masm.ma_cmp(dest, Imm32(0));
if (!bailoutIf(Assembler::LessThan, ins->snapshot()))

View File

@ -1104,7 +1104,7 @@ CodeGeneratorX86Shared::visitShiftI(LShiftI *ins)
case JSOP_URSH:
if (shift) {
masm.shrl(Imm32(shift), lhs);
} else if (ins->mir()->toUrsh()->canOverflow()) {
} else if (ins->mir()->toUrsh()->fallible()) {
// x >>> 0 can overflow.
masm.testl(lhs, lhs);
if (!bailoutIf(Assembler::Signed, ins->snapshot()))
@ -1125,7 +1125,7 @@ CodeGeneratorX86Shared::visitShiftI(LShiftI *ins)
break;
case JSOP_URSH:
masm.shrl_cl(lhs);
if (ins->mir()->toUrsh()->canOverflow()) {
if (ins->mir()->toUrsh()->fallible()) {
// x >>> 0 can overflow.
masm.testl(lhs, lhs);
if (!bailoutIf(Assembler::Signed, ins->snapshot()))