Backout 7895a56d434d, 2520fd9f3883, bca9d7ef2727, ba4e134b13fd (bug 765119) for make check failures
authorEd Morley <emorley@mozilla.com>
Tue, 02 Oct 2012 10:58:37 +0100
changeset 108994 c76b04f5a2b5ecf24cc7509ce3b4e501453cecbd
parent 108993 15ec3a643b0b95810d86e211472607890549848c
child 108995 da5df2c1ae16428cd4827ab31b6562a519e7e9d3
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
bugs765119
milestone18.0a1
backs out7895a56d434da2e97879ad4ae62395a0312ac809
Backout 7895a56d434d, 2520fd9f3883, bca9d7ef2727, ba4e134b13fd (bug 765119) for make check failures
js/src/ion/Ion.h
js/src/ion/JSONSpewer.cpp
js/src/ion/MIR.cpp
js/src/ion/MIR.h
js/src/ion/MIRGraph.cpp
js/src/ion/MIRGraph.h
js/src/ion/RangeAnalysis.cpp
js/src/ion/RangeAnalysis.h
js/src/ion/arm/CodeGenerator-arm.cpp
--- a/js/src/ion/Ion.h
+++ b/js/src/ion/Ion.h
@@ -160,17 +160,17 @@ struct IonOptions
       : gvn(true),
         gvnIsOptimistic(true),
         licm(true),
         osr(true),
         limitScriptSize(true),
         lsra(true),
         inlining(true),
         edgeCaseAnalysis(true),
-        rangeAnalysis(true),
+        rangeAnalysis(false),
         parallelCompilation(false),
         usesBeforeCompile(10240),
         usesBeforeCompileNoJaeger(40),
         usesBeforeInlining(usesBeforeCompile),
         maxStackArgs(4096),
         maxInlineDepth(3),
         smallFunctionMaxBytecodeLength(100),
         smallFunctionUsesBeforeInlining(usesBeforeInlining / 4),
--- a/js/src/ion/JSONSpewer.cpp
+++ b/js/src/ion/JSONSpewer.cpp
@@ -250,18 +250,17 @@ JSONSpewer::spewMDef(MDefinition *def)
         integerValue(def->getOperand(i)->id());
     endList();
 
     beginListProperty("uses");
     for (MUseDefIterator use(def); use; use++)
         integerValue(use.def()->id());
     endList();
 
-    stringProperty("type", "%s : [%d, %d]", StringFromMIRType(def->type()),
-                   def->range()->lower(), def->range()->upper());
+    stringProperty("type", StringFromMIRType(def->type()));
 
     if (def->isInstruction()) {
         if (MResumePoint *rp = def->toInstruction()->resumePoint())
             spewMResumePoint(rp);
     }
 
     endObject();
 }
--- a/js/src/ion/MIR.cpp
+++ b/js/src/ion/MIR.cpp
@@ -5,17 +5,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "IonBuilder.h"
 #include "LICM.h" // For LinearSum
 #include "MIR.h"
 #include "MIRGraph.h"
 #include "EdgeCaseAnalysis.h"
-#include "IonSpewer.h"
 #include "jsnum.h"
 #include "jsstr.h"
 #include "jsatominlines.h"
 #include "jstypedarrayinlines.h" // For ClampIntForUint8Array
 
 using namespace js;
 using namespace js::ion;
 
@@ -29,33 +28,16 @@ MDefinition::PrintOpcodeName(FILE *fp, M
 #undef NAME
     };
     const char *name = names[op];
     size_t len = strlen(name);
     for (size_t i = 0; i < len; i++)
         fprintf(fp, "%c", tolower(name[i]));
 }
 
-// If one of the inputs to any non-phi are in a block that will abort, then there is
-// no point in processing this instruction, since control flow cannot reach here.
-bool
-MDefinition::earlyAbortCheck()
-{
-    if (isPhi())
-        return false;
-    for (int i = 0; i < numOperands(); i++) {
-        if (getOperand(i)->block()->earlyAbort()) {
-            block()->setEarlyAbort();
-            IonSpew(IonSpew_Range, "Ignoring value from block %d because instruction %d is in a block that aborts", block()->id(), getOperand(i)->id());
-            return true;
-        }
-    }
-    return false;
-}
-
 static inline bool
 EqualValues(bool useGVN, MDefinition *left, MDefinition *right)
 {
     if (useGVN)
         return left->valueNumber() == right->valueNumber();
 
     return left->id() == right->id();
 }
@@ -471,65 +453,16 @@ MPhi::congruentTo(MDefinition *const &in
 
 bool
 MPhi::addInput(MDefinition *ins)
 {
     ins->addUse(this, inputs_.length());
     return inputs_.append(ins);
 }
 
-bool
-MPhi::recomputeRange()
-{
-    if (type() != MIRType_Int32)
-        return false;
-
-    Range r;
-    JS_ASSERT(getOperand(0)->op() != MDefinition::Op_OsrValue);
-    bool updated = false;
-    for (size_t i = 0; i < numOperands(); i++) {
-        if (getOperand(i)->block()->earlyAbort()) {
-            IonSpew(IonSpew_Range, "Ignoring unreachable input %d", getOperand(i)->id());
-            continue;
-        }
-
-        if (!isOSRLikeValue(getOperand(i))) {
-            if (block()->isLoopHeader())
-                changeCounts_[i].updateRange(getOperand(i)->range());
-            if (updated) {
-                if (block()->isLoopHeader())
-                    r.unionWith(&changeCounts_[i]);
-                else
-                    r.unionWith(getOperand(i)->range());
-            } else {
-                r.update(getOperand(0)->range());
-                updated = true;
-            }
-#ifdef DEBUG
-            if (IonSpewEnabled(IonSpew_Range)) {
-                fprintf(IonSpewFile, "    %d:", getOperand(i)->id());
-                getOperand(i)->range()->printRange(IonSpewFile);
-                fprintf(IonSpewFile, " => ");
-                r.printRange(IonSpewFile);
-                fprintf(IonSpewFile, "\n");
-            }
-#endif
-
-
-        }
-     }
-     if (!updated) {
-         IonSpew(IonSpew_Range, "My block is unreachable %d", id());
-         block()->setEarlyAbort();
-         return false;
-     }
-
-     return range()->update(&r);
-}
-
 uint32
 MPrepareCall::argc() const
 {
     JS_ASSERT(useCount() == 1);
     MCall *call = usesBegin()->node()->toDefinition()->toCall();
     return call->numStackArgs();
 }
 
@@ -1525,20 +1458,8 @@ void
 MBeta::printOpcode(FILE *fp)
 {
     PrintOpcodeName(fp, op());
     fprintf(fp, " ");
     getOperand(0)->printName(fp);
     fprintf(fp, " ");
     comparison_.printRange(fp);
 }
-
-bool
-MBeta::recomputeRange()
-{
-    bool nullRange = false;
-    bool ret = range()->update(Range::intersect(val_->range(), &comparison_, &nullRange));
-    if (nullRange) {
-            IonSpew(IonSpew_Range, "Marking block for inst %d unexitable", id());
-            block()->setEarlyAbort();
-    }
-    return ret;
-}
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -56,18 +56,16 @@ MIRType MIRTypeFromValue(const js::Value
 class MDefinition;
 class MInstruction;
 class MBasicBlock;
 class MNode;
 class MUse;
 class MIRGraph;
 class MResumePoint;
 
-static inline bool isOSRLikeValue (MDefinition *def);
-
 // Represents a use of a node.
 class MUse : public TempObject, public InlineForwardListNode<MUse>
 {
     friend class MDefinition;
 
     MNode *node_;           // The node that is using this operand.
     uint32 index_;          // The index of this operand in its owner.
 
@@ -300,17 +298,17 @@ class MDefinition : public MNode
     virtual bool congruentTo(MDefinition* const &ins) const {
         return false;
     }
     bool congruentIfOperandsEqual(MDefinition * const &ins) const;
     virtual MDefinition *foldsTo(bool useValueNumbers);
     virtual void analyzeEdgeCasesForward();
     virtual void analyzeEdgeCasesBackward();
     virtual void analyzeTruncateBackward();
-    bool earlyAbortCheck();
+
     // Propagate a range. Return true if the range changed.
     virtual bool recomputeRange() {
         return false;
     }
 
     MNode::Kind kind() const {
         return MNode::Definition;
     }
@@ -1916,22 +1914,16 @@ class MBitAnd : public MBinaryBitwiseIns
         return getOperand(operand); // 0 & x => 0;
     }
     MDefinition *foldIfNegOne(size_t operand) {
         return getOperand(1 - operand); // x & -1 => x
     }
     MDefinition *foldIfEqual() {
         return getOperand(0); // x & x => x;
     }
-    bool recomputeRange() {
-        Range *left = getOperand(0)->range();
-        Range *right = getOperand(1)->range();
-        return range()->update(Range::and_(left, right));
-    }
-
 };
 
 class MBitOr : public MBinaryBitwiseInstruction
 {
     MBitOr(MDefinition *left, MDefinition *right)
       : MBinaryBitwiseInstruction(left, right)
     { }
 
@@ -2679,19 +2671,17 @@ class MFromCharCode
 
 class MPhi : public MDefinition, public InlineForwardListNode<MPhi>
 {
     js::Vector<MDefinition *, 2, IonAllocPolicy> inputs_;
     uint32 slot_;
     bool triedToSpecialize_;
     bool hasBytecodeUses_;
     bool isIterator_;
-    // For every input to the phi, track how many times it has changed
-    // Only used in loop headers, so it defaults to 0 elements to conserve space
-    js::Vector<RangeChangeCount, 0, IonAllocPolicy> changeCounts_;
+
     MPhi(uint32 slot)
       : slot_(slot),
         triedToSpecialize_(false),
         hasBytecodeUses_(false),
         isIterator_(false)
     {
         setResultType(MIRType_Value);
     }
@@ -2738,49 +2728,61 @@ class MPhi : public MDefinition, public 
     }
     void setIterator() {
         isIterator_ = true;
     }
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
-    bool recomputeRange();
-    bool initCounts() {
-        return changeCounts_.resize(inputs_.length());
+
+    bool recomputeRange() {
+        if (type() != MIRType_Int32)
+            return false;
+
+        Range r;
+        r.update(getOperand(0)->range());
+
+        for (size_t i = 0; i < numOperands(); i++)
+            r.unionWith(getOperand(i)->range());
+
+        return range()->update(&r);
     }
 };
 
 // The goal of a Beta node is to split a def at a conditionally taken
 // branch, so that uses dominated by it have a different name.
 class MBeta : public MUnaryInstruction
 {
   private:
     Range comparison_;
     MDefinition *val_;
-    MBeta(MDefinition *val, const Range &comp)
+    MBeta(MDefinition *val, int32 low, int32 high)
         : MUnaryInstruction(val),
-          comparison_(comp),
+          comparison_(low, high),
           val_(val)
     {
     }
 
   public:
     INSTRUCTION_HEADER(Beta);
     void printOpcode(FILE *fp);
-    static MBeta *New(MDefinition *val, const Range &comp)
+    static MBeta *New(MDefinition *val, int32 low, int32 high)
     {
-        return new MBeta(val, comp);
+        return new MBeta(val, low, high);
     }
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 
-    bool recomputeRange();
+    bool recomputeRange() {
+        return range()->update(
+            Range::intersect(val_->range(), &comparison_));
+    }
 };
 
 // MIR representation of a Value on the OSR StackFrame.
 // The Value is indexed off of OsrFrameReg.
 class MOsrValue : public MUnaryInstruction
 {
   private:
     ptrdiff_t frameOffset_;
@@ -5527,26 +5529,16 @@ MInstruction *MDefinition::toInstruction
     return (MInstruction *)this;
 }
 
 void MNode::initOperand(size_t index, MDefinition *ins)
 {
     setOperand(index, ins);
     ins->addUse(this, index);
 }
-static inline bool isOSRLikeValue (MDefinition *def) {
-    if (def->isOsrValue())
-        return true;
-
-    if (def->isUnbox())
-        if (def->getOperand(0)->isOsrValue())
-            return true;
-
-    return false;
-}
 
 typedef Vector<MDefinition *, 8, IonAllocPolicy> MDefinitionVector;
 
 } // namespace ion
 } // namespace js
 
 #endif // jsion_mir_h__
 
--- a/js/src/ion/MIRGraph.cpp
+++ b/js/src/ion/MIRGraph.cpp
@@ -112,18 +112,17 @@ MBasicBlock::NewPendingLoopHeader(MIRGra
 
 MBasicBlock *
 MBasicBlock::NewSplitEdge(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred)
 {
     return MBasicBlock::New(graph, info, pred, pred->pc(), SPLIT_EDGE);
 }
 
 MBasicBlock::MBasicBlock(MIRGraph &graph, CompileInfo &info, jsbytecode *pc, Kind kind)
-    : earlyAbort_(false),
-    graph_(graph),
+  : graph_(graph),
     info_(info),
     stackPosition_(info_.firstStackSlot()),
     lastIns_(NULL),
     pc_(pc),
     lir_(NULL),
     start_(NULL),
     entryResumePoint_(NULL),
     successorWithPhis_(NULL),
--- a/js/src/ion/MIRGraph.h
+++ b/js/src/ion/MIRGraph.h
@@ -48,20 +48,16 @@ class MBasicBlock : public TempObject, p
   private:
     MBasicBlock(MIRGraph &graph, CompileInfo &info, jsbytecode *pc, Kind kind);
     bool init();
     void copySlots(MBasicBlock *from);
     bool inherit(MBasicBlock *pred);
     bool inheritResumePoint(MBasicBlock *pred);
     void assertUsesAreNotWithin(MUseIterator use, MUseIterator end);
 
-    // Does this block do something that forces it to terminate early?
-    bool earlyAbort_;
-
-
     // Sets a slot, taking care to rewrite copies.
     void setSlot(uint32 slot, MDefinition *ins);
 
     // Pushes a copy of a local variable or argument.
     void pushVariable(uint32 slot);
 
     // Sets a variable slot to the top of the stack, correctly creating copies
     // as needed.
@@ -83,25 +79,17 @@ class MBasicBlock : public TempObject, p
                                              MBasicBlock *pred, jsbytecode *entryPc);
     static MBasicBlock *NewSplitEdge(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred);
 
     bool dominates(MBasicBlock *other);
 
     void setId(uint32 id) {
         id_ = id;
     }
-    void setEarlyAbort() {
-        earlyAbort_ = true;
-    }
-    void clearEarlyAbort() {
-        earlyAbort_ = false;
-    }
-    bool earlyAbort() {
-        return earlyAbort_;
-    }
+
     // Move the definition to the top of the stack.
     void pick(int32 depth);
 
     // Exchange 2 stack slots at the defined depth
     void swapAt(int32 depth);
 
     // Gets the instruction associated with various slot types.
     MDefinition *peek(int32 depth);
--- a/js/src/ion/RangeAnalysis.cpp
+++ b/js/src/ion/RangeAnalysis.cpp
@@ -157,57 +157,58 @@ RangeAnalysis::addBetaNobes()
                 smaller = left;
                 greater = right;
             } else if (JSOP_GT) {
                 smaller = right;
                 greater = left;
             }
             if (smaller && greater) {
                 MBeta *beta;
-                beta = MBeta::New(smaller, Range(JSVAL_INT_MIN, JSVAL_INT_MAX-1));
+                beta = MBeta::New(smaller, JSVAL_INT_MIN, JSVAL_INT_MAX-1);
                 block->insertBefore(*block->begin(), beta);
                 replaceDominatedUsesWith(smaller, beta, block);
-                beta = MBeta::New(greater, Range(JSVAL_INT_MIN+1, JSVAL_INT_MAX));
+                beta = MBeta::New(greater, JSVAL_INT_MIN+1, JSVAL_INT_MAX);
                 block->insertBefore(*block->begin(), beta);
                 replaceDominatedUsesWith(greater, beta, block);
             }
             continue;
         }
 
         JS_ASSERT(val);
 
 
-        Range comp;
+        int32 low = JSVAL_INT_MIN;
+        int32 high = JSVAL_INT_MAX;
         switch (jsop) {
           case JSOP_LE:
-            comp.setUpper(bound);
+            high = bound;
             break;
           case JSOP_LT:
             if (!SafeSub(bound, 1, &bound))
                 break;
-            comp.setUpper(bound);
+            high = bound;
             break;
           case JSOP_GE:
-            comp.setLower(bound);
+            low = bound;
             break;
           case JSOP_GT:
             if (!SafeAdd(bound, 1, &bound))
                 break;
-            comp.setLower(bound);
+            low = bound;
             break;
           case JSOP_EQ:
-            comp.setLower(bound);
-            comp.setUpper(bound);
+            low = bound;
+            high = bound;
           default:
             break; // well, for neq we could have
                    // [-\inf, bound-1] U [bound+1, \inf] but we only use contiguous ranges.
         }
 
         IonSpew(IonSpew_Range, "Adding beta node for %d", val->id());
-        MBeta *beta = MBeta::New(val, comp);
+        MBeta *beta = MBeta::New(val, low, high);
         block->insertBefore(*block->begin(), beta);
         replaceDominatedUsesWith(val, beta, block);
     }
 
     return true;
 }
 
 bool
@@ -244,17 +245,17 @@ Range::printRange(FILE *fp)
     fprintf(fp, "[");
     if (lower_infinite_) { fprintf(fp, "-inf"); } else { fprintf(fp, "%d", lower_); }
     fprintf(fp, ", ");
     if (upper_infinite_) { fprintf(fp, "inf"); } else { fprintf(fp, "%d", upper_); }
     fprintf(fp, "]");
 }
 
 Range
-Range::intersect(const Range *lhs, const Range *rhs, bool *nullRange)
+Range::intersect(const Range *lhs, const Range *rhs)
 {
     Range r(
         Max(lhs->lower_, rhs->lower_),
         Min(lhs->upper_, rhs->upper_));
 
     r.lower_infinite_ = lhs->lower_infinite_ && rhs->lower_infinite_;
     r.upper_infinite_ = lhs->upper_infinite_ && rhs->upper_infinite_;
 
@@ -275,112 +276,77 @@ Range::intersect(const Range *lhs, const
     if (r.upper_ < r.lower_)
         r.makeRangeInfinite();
     return r;
 }
 
 void
 Range::unionWith(const Range *other)
 {
-   setLower(Min(lower_, other->lower_));
-   lower_infinite_ |= other->lower_infinite_;
-   setUpper(Max(upper_, other->upper_));
-   upper_infinite_ |= other->upper_infinite_;
-}
-
-void
-Range::unionWith(RangeChangeCount *other)
-{
-    if (other->lowerCount_ <= 2) {
-        setLower(Min(lower_, other->oldRange.lower_));
-        lower_infinite_ |= other->oldRange.lower_infinite_;
-    } else {
-        other->lowerCount_ = 0;
-    }
-    if (other->upperCount_ <= 2) {
-        setUpper(Max(upper_, other->oldRange.upper_));
-        upper_infinite_ |= other->oldRange.upper_infinite_;
-    } else {
-        other->upperCount_ = 0;
-    }
+    setLower(Min(lower_, other->lower_));
+    setUpper(Max(upper_, other->upper_));
+    lower_infinite_ |= other->lower_infinite_;
+    upper_infinite_ |= other->upper_infinite_;
 }
 
 Range
 Range::add(const Range *lhs, const Range *rhs)
 {
-    Range ret(
+    return Range(
         (int64_t)lhs->lower_ + (int64_t)rhs->lower_,
         (int64_t)lhs->upper_ + (int64_t)rhs->upper_);
-    return ret;
 }
 
 Range
 Range::sub(const Range *lhs, const Range *rhs)
 {
-    Range ret(
+    return Range(
         (int64_t)lhs->lower_ - (int64_t)rhs->upper_,
         (int64_t)lhs->upper_ - (int64_t)rhs->lower_);
-    return ret;
+}
 
-}
-Range
-Range::and_(const Range *lhs, const Range *rhs)
-{
-    uint64_t lower = 0;
-    // If both numbers can be negative, issues can be had.
-    if (lhs->lower_ < 0 && rhs->lower_ < 0)
-        lower = INT_MIN;
-    uint64_t upper = lhs->upper_;
-    if (rhs->upper_ < lhs->upper_)
-        upper = rhs->upper_;
-    Range ret(lower, upper);
-    return ret;
-
-}
 Range
 Range::mul(const Range *lhs, const Range *rhs)
 {
     int64_t a = (int64_t)lhs->lower_ * (int64_t)rhs->lower_;
     int64_t b = (int64_t)lhs->lower_ * (int64_t)rhs->upper_;
     int64_t c = (int64_t)lhs->upper_ * (int64_t)rhs->lower_;
     int64_t d = (int64_t)lhs->upper_ * (int64_t)rhs->upper_;
-    Range ret(
+    return Range(
         Min( Min(a, b), Min(c, d) ),
         Max( Max(a, b), Max(c, d) ));
-    return ret;
 }
 
 Range
 Range::shl(const Range *lhs, int32 c)
 {
     int32 shift = c & 0x1f;
-    Range ret(
+    return Range(
         (int64_t)lhs->lower_ << shift,
         (int64_t)lhs->upper_ << shift);
-    return ret;
 }
 
 Range
 Range::shr(const Range *lhs, int32 c)
 {
     int32 shift = c & 0x1f;
-    Range ret(
+    return Range(
         (int64_t)lhs->lower_ >> shift,
         (int64_t)lhs->upper_ >> shift);
-    return ret;
 }
 
 bool
 Range::update(const Range *other)
 {
     bool changed =
         lower_ != other->lower_ ||
         lower_infinite_ != other->lower_infinite_ ||
         upper_ != other->upper_ ||
         upper_infinite_ != other->upper_infinite_;
+
     if (changed) {
         lower_ = other->lower_;
         lower_infinite_ = other->lower_infinite_;
         upper_ = other->upper_;
         upper_infinite_ = other->upper_infinite_;
     }
 
     return changed;
@@ -403,56 +369,55 @@ PopFromWorklist(MDefinitionVector &workl
     def->setNotInWorklist();
     return def;
 }
 
 
 bool
 RangeAnalysis::analyze()
 {
-    for (PostorderIterator i(graph_.poBegin()); i != graph_.poEnd(); i++) {
-        MBasicBlock *curBlock = *i;
-        if (!curBlock->isLoopHeader())
-            continue;
-        for (MPhiIterator pi(curBlock->phisBegin()); pi != curBlock->phisEnd(); pi++)
-            if (!pi->initCounts())
-                return false;
-    }
-
     IonSpew(IonSpew_Range, "Doing range propagation");
     MDefinitionVector worklist;
 
     for (ReversePostorderIterator block(graph_.rpoBegin()); block != graph_.rpoEnd(); block++) {
         for (MDefinitionIterator iter(*block); iter; iter++) {
             MDefinition *def = *iter;
 
+            if (!def->isPhi() && !def->isBeta())
+                continue;
             AddToWorklist(worklist, def);
 
         }
     }
     size_t iters = 0;
-
-    while (!worklist.empty()) {
+#define MAX_ITERS 4096
+    // XXX: hack: range analysis iloops on jit-test/tests/basic/fannkuch.js
+    // To circumvent this and land the pass, we just run for a fixed number of
+    // iterations.
+    //
+    // (Bug 765119)
+    while (!worklist.empty() /* && iters < MAX_ITERS*/) {
         MDefinition *def = PopFromWorklist(worklist);
         IonSpew(IonSpew_Range, "recomputing range on %d", def->id());
         SpewRange(def);
-        if (!def->earlyAbortCheck() && def->recomputeRange()) {
+        if (def->recomputeRange()) {
             JS_ASSERT(def->range()->lower() <= def->range()->upper());
             IonSpew(IonSpew_Range, "Range changed; adding consumers");
             for (MUseDefIterator use(def); use; use++) {
                 if(!AddToWorklist(worklist, use.def()))
                     return false;
             }
         }
         iters++;
     }
     // Cleanup (in case we stopped due to MAX_ITERS)
     for(size_t i = 0; i < worklist.length(); i++)
         worklist[i]->setNotInWorklist();
 
+#undef MAX_ITERS
 
 #ifdef DEBUG
     for (ReversePostorderIterator block(graph_.rpoBegin()); block != graph_.rpoEnd(); block++) {
         for (MDefinitionIterator iter(*block); iter; iter++) {
             MDefinition *def = *iter;
             SpewRange(def);
             JS_ASSERT(def->range()->lower() <= def->range()->upper());
             JS_ASSERT(!def->isInWorklist());
--- a/js/src/ion/RangeAnalysis.h
+++ b/js/src/ion/RangeAnalysis.h
@@ -16,183 +16,159 @@ namespace js {
 namespace ion {
 
 class MBasicBlock;
 class MIRGraph;
 
 class RangeAnalysis
 {
   protected:
-    bool blockDominates(MBasicBlock *b, MBasicBlock *b2);
-    void replaceDominatedUsesWith(MDefinition *orig, MDefinition *dom,
-                                  MBasicBlock *block);
+	bool blockDominates(MBasicBlock *b, MBasicBlock *b2);
+	void replaceDominatedUsesWith(MDefinition *orig, MDefinition *dom,
+	                              MBasicBlock *block);
 
   protected:
     MIRGraph &graph_;
 
   public:
     RangeAnalysis(MIRGraph &graph);
     bool addBetaNobes();
     bool analyze();
     bool removeBetaNobes();
 };
 
-struct RangeChangeCount;
 class Range {
-  private:
-    // :TODO: we should do symbolic range evaluation, where we have
-    // information of the form v1 < v2 for arbitrary defs v1 and v2, not
-    // just constants of type int32.
-    // (Bug 766592)
-
-    // We represent ranges where the endpoints can be in the set:
-    // {-infty} U [INT_MIN, INT_MAX] U {infty}.  A bound of +/-
-    // infty means that the value may have overflowed in that
-    // direction. When computing the range of an integer
-    // instruction, the ranges of the operands can be clamped to
-    // [INT_MIN, INT_MAX], since if they had overflowed they would
-    // no longer be integers. This is important for optimizations
-    // and somewhat subtle.
-    //
-    // N.B.: All of the operations that compute new ranges based
-    // on existing ranges will ignore the _infinite_ flags of the
-    // input ranges; that is, they implicitly clamp the ranges of
-    // the inputs to [INT_MIN, INT_MAX]. Therefore, while our range might
-    // be infinite (and could overflow), when using this information to
-    // propagate through other ranges, we disregard this fact; if that code
-    // executes, then the overflow did not occur, so we may safely assume
-    // that the range is [INT_MIN, INT_MAX] instead.
-    //
-    // To facilitate this trick, we maintain the invariants that:
-    // 1) lower_infinite == true implies lower_ == JSVAL_INT_MIN
-    // 2) upper_infinite == true implies upper_ == JSVAL_INT_MAX
-    int32 lower_;
-    bool lower_infinite_;
-    int32 upper_;
-    bool upper_infinite_;
+    private:
+        // :TODO: we should do symbolic range evaluation, where we have
+        // information of the form v1 < v2 for arbitrary defs v1 and v2, not
+        // just constants of type int32.
+        // (Bug 766592)
 
-  public:
-    Range()
-        : lower_(JSVAL_INT_MIN),
-          lower_infinite_(true),
-          upper_(JSVAL_INT_MAX),
-          upper_infinite_(true)
-    {}
-
-    Range(int64_t l, int64_t h) {
-        setLower(l);
-        setUpper(h);
-    }
+        // We represent ranges where the endpoints can be in the set:
+        // {-infty} U [INT_MIN, INT_MAX] U {infty}.  A bound of +/-
+        // infty means that the value may have overflowed in that
+        // direction. When computing the range of an integer
+        // instruction, the ranges of the operands can be clamped to
+        // [INT_MIN, INT_MAX], since if they had overflowed they would
+        // no longer be integers. This is important for optimizations
+        // and somewhat subtle.
+        //
+        // N.B.: All of the operations that compute new ranges based
+        // on existing ranges will ignore the _infinite_ flags of the
+        // input ranges; that is, they implicitly clamp the ranges of
+        // the inputs to [INT_MIN, INT_MAX]. Therefore, while our range might
+        // be infinite (and could overflow), when using this information to
+        // propagate through other ranges, we disregard this fact; if that code
+        // executes, then the overflow did not occur, so we may safely assume
+        // that the range is [INT_MIN, INT_MAX] instead.
+        //
+        // To facilitate this trick, we maintain the invariants that:
+        // 1) lower_infinite == true implies lower_ == JSVAL_INT_MIN
+        // 2) upper_infinite == true implies upper_ == JSVAL_INT_MAX
+        int32 lower_;
+        bool lower_infinite_;
+        int32 upper_;
+        bool upper_infinite_;
 
-    Range(const Range &other)
-    : lower_(other.lower_),
-      lower_infinite_(other.lower_infinite_),
-      upper_(other.upper_),
-      upper_infinite_(other.upper_infinite_)
-    {}
+    public:
+        Range() :
+            lower_(JSVAL_INT_MIN),
+            lower_infinite_(true),
+            upper_(JSVAL_INT_MAX),
+            upper_infinite_(true)
+        {}
 
-    static int64_t abs64(int64_t x) {
+        Range(int64_t l, int64_t h) {
+            setLower(l);
+            setUpper(h);
+        }
+
+        static int64_t abs64(int64_t x) {
 #ifdef WTF_OS_WINDOWS
-        return _abs64(x);
+            return _abs64(x);
 #else
-        return llabs(x);
+            return llabs(x);
 #endif
-    }
+        }
 
-    void printRange(FILE *fp);
-    bool update(const Range *other);
-    bool update(const Range &other) {
-        return update(&other);
-    }
+        void printRange(FILE *fp);
+        bool update(const Range *other);
+        bool update(const Range &other) {
+            return update(&other);
+        }
 
-    // Unlike the other operations, unionWith is an in-place
-    // modification. This is to avoid a bunch of useless extra
-    // copying when chaining together unions when handling Phi
-    // nodes.
-    void unionWith(const Range *other);
-    void unionWith(RangeChangeCount *other);
-    static Range intersect(const Range *lhs, const Range *rhs, bool *nullRange);
-    static Range add(const Range *lhs, const Range *rhs);
-    static Range sub(const Range *lhs, const Range *rhs);
-    static Range mul(const Range *lhs, const Range *rhs);
-    static Range and_(const Range *lhs, const Range *rhs);
-    static Range shl(const Range *lhs, int32 c);
-    static Range shr(const Range *lhs, int32 c);
+        // Unlike the other operations, unionWith is an in-place
+        // modification. This is to avoid a bunch of useless extra
+        // copying when chaining together unions when handling Phi
+        // nodes.
+        void unionWith(const Range *other);
+
+        static Range intersect(const Range *lhs, const Range *rhs);
+        static Range add(const Range *lhs, const Range *rhs);
+        static Range sub(const Range *lhs, const Range *rhs);
+        static Range mul(const Range *lhs, const Range *rhs);
+
+        static Range shl(const Range *lhs, int32 c);
+        static Range shr(const Range *lhs, int32 c);
 
-    inline void makeLowerInfinite() {
-        lower_infinite_ = true;
-        lower_ = JSVAL_INT_MIN;
-    }
-    inline void makeUpperInfinite() {
-        upper_infinite_ = true;
-        upper_ = JSVAL_INT_MAX;
-    }
-    inline void makeRangeInfinite() {
-        makeLowerInfinite();
-        makeUpperInfinite();
-    }
+        inline void makeLowerInfinite() {
+            lower_infinite_ = true;
+            lower_ = JSVAL_INT_MIN;
+        }
+        inline void makeUpperInfinite() {
+            upper_infinite_ = true;
+            upper_ = JSVAL_INT_MAX;
+        }
+        inline void makeRangeInfinite() {
+            makeLowerInfinite();
+            makeUpperInfinite();
+        }
 
-    inline bool isLowerInfinite() const {
-        return lower_infinite_;
-    }
-    inline bool isUpperInfinite() const {
-        return upper_infinite_;
-    }
-
-    inline bool isFinite() const {
-        return !isLowerInfinite() && !isUpperInfinite();
-    }
-
-    inline int32 lower() const {
-        return lower_;
-    }
+        inline bool isLowerInfinite() const {
+            return lower_infinite_;
+        }
+        inline bool isUpperInfinite() const {
+            return upper_infinite_;
+        }
 
-    inline int32 upper() const {
-        return upper_;
-    }
+        inline bool isFinite() const {
+            return !isLowerInfinite() && !isUpperInfinite();
+        }
 
-    inline void setLower(int64_t x) {
-        if (x > JSVAL_INT_MAX) { // c.c
-            lower_ = JSVAL_INT_MAX;
-        } else if (x < JSVAL_INT_MIN) {
-            makeLowerInfinite();
-        } else {
-            lower_ = (int32)x;
-            lower_infinite_ = false;
+        inline int32 lower() const {
+            return lower_;
+        }
+
+        inline int32 upper() const {
+            return upper_;
         }
-    }
-    inline void setUpper(int64_t x) {
-        if (x > JSVAL_INT_MAX) {
-            makeUpperInfinite();
-        } else if (x < JSVAL_INT_MIN) { // c.c
-            upper_ = JSVAL_INT_MIN;
-        } else {
-            upper_ = (int32)x;
-            upper_infinite_ = false;
+
+        inline void setLower(int64_t x) {
+            if (x > JSVAL_INT_MAX) { // c.c
+                lower_ = JSVAL_INT_MAX;
+            } else if (x < JSVAL_INT_MIN) {
+                makeLowerInfinite();
+            } else {
+                lower_ = (int32)x;
+                lower_infinite_ = false;
+            }
         }
-    }
-    void set(int64_t l, int64_t h) {
-        setLower(l);
-        setUpper(h);
-    }
-};
-
-struct RangeChangeCount {
-    Range oldRange;
-    unsigned char lowerCount_ : 4;
-    unsigned char upperCount_ : 4;
-
-    void updateRange(Range *newRange) {
-        JS_ASSERT(newRange->lower() >= oldRange.lower());
-        if (newRange->lower() != oldRange.lower())
-            lowerCount_ = lowerCount_ < 15 ? lowerCount_ + 1 : lowerCount_;
-        JS_ASSERT(newRange->upper() <= oldRange.upper());
-        if (newRange->upper() != oldRange.upper())
-            upperCount_ = upperCount_ < 15 ? upperCount_ + 1 : upperCount_;
-        oldRange = *newRange;
-    }
+        inline void setUpper(int64_t x) {
+            if (x > JSVAL_INT_MAX) {
+                makeUpperInfinite();
+            } else if (x < JSVAL_INT_MIN) { // c.c
+                upper_ = JSVAL_INT_MIN;
+            } else {
+                upper_ = (int32)x;
+                upper_infinite_ = false;
+            }
+        }
+        void set(int64_t l, int64_t h) {
+            setLower(l);
+            setUpper(h);
+        }
 };
 
 } // namespace ion
 } // namespace js
 
 #endif // jsion_range_analysis_h__
 
--- a/js/src/ion/arm/CodeGenerator-arm.cpp
+++ b/js/src/ion/arm/CodeGenerator-arm.cpp
@@ -462,20 +462,22 @@ CodeGeneratorARM::visitMulI(LMulI *ins)
         }
         // Bailout on overflow
         if (mul->canOverflow() && !bailoutIf(c, ins->snapshot()))
             return false;
     } else {
         Assembler::Condition c = Assembler::Overflow;
 
         //masm.imull(ToOperand(rhs), ToRegister(lhs));
-        if (mul->canOverflow())
+        if (mul->canOverflow()) {
             c = masm.ma_check_mul(ToRegister(lhs), ToRegister(rhs), ToRegister(dest), c);
-        else
+        } else {
             masm.ma_mul(ToRegister(lhs), ToRegister(rhs), ToRegister(dest));
+        }
+
 
         // Bailout on overflow
         if (mul->canOverflow() && !bailoutIf(c, ins->snapshot()))
             return false;
 
         if (mul->canBeNegativeZero()) {
             Label done;
             masm.ma_cmp(ToRegister(dest), Imm32(0));