From fd8c03c20577c71ab905b7fb14534d9434951237 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 15 Oct 2013 20:49:44 -0700 Subject: [PATCH] Bug 925586 - IonMonkey: Document MUrsh's special case exemption from type() rules, and restrict it to only the cases that need it. r=nbp --- js/src/jit/LIR-Common.h | 4 ++-- js/src/jit/MIR.cpp | 13 +++++++++--- js/src/jit/MIR.h | 20 ++++++++++++------- js/src/jit/RangeAnalysis.cpp | 10 ++++++++-- js/src/jit/RangeAnalysis.h | 8 -------- js/src/jit/arm/CodeGenerator-arm.cpp | 4 ++-- .../jit/shared/CodeGenerator-x86-shared.cpp | 4 ++-- 7 files changed, 37 insertions(+), 26 deletions(-) diff --git a/js/src/jit/LIR-Common.h b/js/src/jit/LIR-Common.h index 3c236bae764..a68f566f960 100644 --- a/js/src/jit/LIR-Common.h +++ b/js/src/jit/LIR-Common.h @@ -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_]; } diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 14c36809db2..97bcda507cd 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -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; } diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 10e4fbd8089..8c4cb552ae6 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -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(this); \ + } \ + const M##opcode *MDefinition::to##opcode() const \ + { \ + JS_ASSERT(is##opcode()); \ + return static_cast(this); \ } MIR_OPCODE_LIST(OPCODE_CASTS) #undef OPCODE_CASTS diff --git a/js/src/jit/RangeAnalysis.cpp b/js/src/jit/RangeAnalysis.cpp index df2d6616a8d..00e7d974894 100644 --- a/js/src/jit/RangeAnalysis.cpp +++ b/js/src/jit/RangeAnalysis.cpp @@ -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 diff --git a/js/src/jit/RangeAnalysis.h b/js/src/jit/RangeAnalysis.h index 03eeae545b2..5cd1c6f4322 100644 --- a/js/src/jit/RangeAnalysis.h +++ b/js/src/jit/RangeAnalysis.h @@ -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_; } diff --git a/js/src/jit/arm/CodeGenerator-arm.cpp b/js/src/jit/arm/CodeGenerator-arm.cpp index ad1f0d44d1d..b5e5754cdb6 100644 --- a/js/src/jit/arm/CodeGenerator-arm.cpp +++ b/js/src/jit/arm/CodeGenerator-arm.cpp @@ -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())) diff --git a/js/src/jit/shared/CodeGenerator-x86-shared.cpp b/js/src/jit/shared/CodeGenerator-x86-shared.cpp index c8b26ed8e15..9e859ca6d50 100644 --- a/js/src/jit/shared/CodeGenerator-x86-shared.cpp +++ b/js/src/jit/shared/CodeGenerator-x86-shared.cpp @@ -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()))