fourthTier: clean up ArithDiv/ArithMod in the DFG
https://bugs.webkit.org/show_bug.cgi?id=116793

Source/JavaScriptCore:

Reviewed by Mark Hahnenberg.

This makes ArithDiv and ArithMod behave similarly, and moves both of their
implementations entirely into DFGSpeculativeJIT.cpp into methods named like
the ones for ArithSub/ArithMul.

Specifically, ArithMod now uses the wrap-in-conversion-nodes idiom that
ArithDiv used for platforms that don't support integer division. Previously
ArithMod had its own int-to-double and double-to-int conversions for this
purpose.

As well, this gets rid of confusing methods like compileSoftModulo() (which
did no such thing, there wasn't anything "soft" about it) and
compileIntegerArithDivForX86() (which is accurately named but we don't use
the platform-specific method convention anywhere else).

Finally, this takes the optimized power-of-two modulo operation that was
previously only for ARMv7s, and makes it available for all platforms. Well,
sort of: I actually rewrote it to do what latest LLVM appears to do, which
is a crazy straight-line power-of-2 modulo based on a combination of shifts,
ands, additions, and subtractions. I can kind of understand it well enough
to see that it complies with both C and JS power-of-2 modulo semantics. I've
also confirmed that it does by testing (hence the corresponding improvements
to one of the division tests). But, I don't claim to know exactly how this
code works other than to observe that it is super leet.

Overall, this patch has the effect of killing some code (no more hackish
int-to-double conversions in ArithMod), making some optimization work on
more platforms, and making the compiler less confusing by doing more things
with the same idiom.

* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::executeEffects):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGSpeculativeJIT.cpp:
(DFG):
(JSC::DFG::SpeculativeJIT::compileArithDiv):
(JSC::DFG::SpeculativeJIT::compileArithMod):
* dfg/DFGSpeculativeJIT.h:
(SpeculativeJIT):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):

LayoutTests:

Reviewed by Mark Hahnenberg.

* fast/js/script-tests/integer-division-neg2tothe32-by-neg1.js:
(myModBy2):
(myModBy1073741824):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153186 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index 259c7a7..834d161 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -568,6 +568,11 @@
     case ArithMod: {
         JSValue left = forNode(node->child1()).value();
         JSValue right = forNode(node->child2()).value();
+        if (node->op() == ArithMod && right && right.isNumber() && right.asNumber() == 1
+            && trySetConstant(node, JSValue(0))) {
+            m_foundConstants = true;
+            break;
+        }
         if (left && right && left.isNumber() && right.isNumber()) {
             double a = left.asNumber();
             double b = right.asNumber();
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index a96194c..a81d6c6 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -211,7 +211,8 @@
             break;
         }
 
-        case ArithDiv: {
+        case ArithDiv:
+        case ArithMod: {
             if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())
                 && node->canSpeculateInteger()) {
                 if (isX86() || isARMv7s()) {
@@ -237,8 +238,7 @@
         }
             
         case ArithMin:
-        case ArithMax:
-        case ArithMod: {
+        case ArithMax: {
             if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())
                 && node->canSpeculateInteger()) {
                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index 4fc9df0..160aadd 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -2816,198 +2816,6 @@
 #endif
 }
 
-void SpeculativeJIT::compileSoftModulo(Node* node)
-{
-    // In the fast path, the dividend value could be the final result
-    // (in case of |dividend| < |divisor|), so we speculate it as strict int32.
-    SpeculateStrictInt32Operand op1(this, node->child1());
-#if CPU(X86) || CPU(X86_64)
-    if (isInt32Constant(node->child2().node())) {
-        int32_t divisor = valueOfInt32Constant(node->child2().node());
-        if (divisor) {
-            GPRReg op1Gpr = op1.gpr();
-
-            GPRTemporary eax(this, X86Registers::eax);
-            GPRTemporary edx(this, X86Registers::edx);
-            GPRTemporary scratch(this);
-            GPRReg scratchGPR = scratch.gpr();
-
-            GPRReg op1SaveGPR;
-            if (op1Gpr == X86Registers::eax || op1Gpr == X86Registers::edx) {
-                op1SaveGPR = allocate();
-                ASSERT(op1Gpr != op1SaveGPR);
-                m_jit.move(op1Gpr, op1SaveGPR);
-            } else
-                op1SaveGPR = op1Gpr;
-            ASSERT(op1SaveGPR != X86Registers::eax);
-            ASSERT(op1SaveGPR != X86Registers::edx);
-
-            m_jit.move(op1Gpr, eax.gpr());
-            m_jit.move(TrustedImm32(divisor), scratchGPR);
-            if (divisor == -1)
-                speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(JITCompiler::Equal, eax.gpr(), TrustedImm32(-2147483647-1)));
-            m_jit.assembler().cdq();
-            m_jit.assembler().idivl_r(scratchGPR);
-            if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
-                // Check that we're not about to create negative zero.
-                JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
-                speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
-                numeratorPositive.link(&m_jit);
-            }
-            if (op1SaveGPR != op1Gpr)
-                unlock(op1SaveGPR);
-
-            integerResult(edx.gpr(), node);
-            return;
-        }
-    }
-#elif CPU(APPLE_ARMV7S) || CPU(ARM_THUMB2)
-    if (isInt32Constant(node->child2().node())) {
-        int32_t divisor = valueOfInt32Constant(node->child2().node());
-        if (divisor > 0 && hasOneBitSet(divisor)) { // If power of 2 then just mask
-            GPRReg dividendGPR = op1.gpr();
-            GPRTemporary result(this);
-            GPRReg resultGPR = result.gpr();
-
-            m_jit.assembler().cmp(dividendGPR, ARMThumbImmediate::makeEncodedImm(0));
-            m_jit.assembler().it(ARMv7Assembler::ConditionLT, false);
-            m_jit.assembler().neg(resultGPR, dividendGPR);
-            m_jit.assembler().mov(resultGPR, dividendGPR);
-            m_jit.and32(TrustedImm32(divisor - 1), resultGPR);
-            m_jit.assembler().it(ARMv7Assembler::ConditionLT);
-            m_jit.assembler().neg(resultGPR, resultGPR);
-
-            if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
-                // Check that we're not about to create negative zero.
-                JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, dividendGPR, TrustedImm32(0));
-                speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, resultGPR));
-                numeratorPositive.link(&m_jit);
-            }
-            integerResult(resultGPR, node);
-            return;
-        }
-    }
-#endif
-
-    SpeculateIntegerOperand op2(this, node->child2());
-#if CPU(X86) || CPU(X86_64)
-    GPRTemporary eax(this, X86Registers::eax);
-    GPRTemporary edx(this, X86Registers::edx);
-    GPRReg op1GPR = op1.gpr();
-    GPRReg op2GPR = op2.gpr();
-    
-    GPRReg op2TempGPR;
-    GPRReg temp;
-    GPRReg op1SaveGPR;
-    
-    if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
-        op2TempGPR = allocate();
-        temp = op2TempGPR;
-    } else {
-        op2TempGPR = InvalidGPRReg;
-        if (op1GPR == X86Registers::eax)
-            temp = X86Registers::edx;
-        else
-            temp = X86Registers::eax;
-    }
-    
-    if (op1GPR == X86Registers::eax || op1GPR == X86Registers::edx) {
-        op1SaveGPR = allocate();
-        ASSERT(op1GPR != op1SaveGPR);
-        m_jit.move(op1GPR, op1SaveGPR);
-    } else
-        op1SaveGPR = op1GPR;
-    
-    ASSERT(temp != op1GPR);
-    ASSERT(temp != op2GPR);
-    ASSERT(op1SaveGPR != X86Registers::eax);
-    ASSERT(op1SaveGPR != X86Registers::edx);
-    
-    m_jit.add32(JITCompiler::TrustedImm32(1), op2GPR, temp);
-    
-    JITCompiler::Jump safeDenominator = m_jit.branch32(JITCompiler::Above, temp, JITCompiler::TrustedImm32(1));
-    
-    JITCompiler::Jump done;
-    // FIXME: if the node is not used as number then we can do this more easily.
-    speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, op2GPR));
-    speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1)));
-    
-    safeDenominator.link(&m_jit);
-            
-    if (op2TempGPR != InvalidGPRReg) {
-        m_jit.move(op2GPR, op2TempGPR);
-        op2GPR = op2TempGPR;
-    }
-            
-    m_jit.move(op1GPR, eax.gpr());
-    m_jit.assembler().cdq();
-    m_jit.assembler().idivl_r(op2GPR);
-            
-    if (op2TempGPR != InvalidGPRReg)
-        unlock(op2TempGPR);
-
-    if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
-        // Check that we're not about to create negative zero.
-        JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
-        speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
-        numeratorPositive.link(&m_jit);
-    }
-    
-    if (op1SaveGPR != op1GPR)
-        unlock(op1SaveGPR);
-            
-    integerResult(edx.gpr(), node);
-
-#elif CPU(APPLE_ARMV7S)
-    GPRTemporary temp(this);
-    GPRTemporary quotientThenRemainder(this);
-    GPRTemporary multiplyAnswer(this);
-    GPRReg dividendGPR = op1.gpr();
-    GPRReg divisorGPR = op2.gpr();
-    GPRReg quotientThenRemainderGPR = quotientThenRemainder.gpr();
-    GPRReg multiplyAnswerGPR = multiplyAnswer.gpr();
-
-    m_jit.assembler().sdiv(quotientThenRemainderGPR, dividendGPR, divisorGPR);
-    speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchMul32(JITCompiler::Overflow, quotientThenRemainderGPR, divisorGPR, multiplyAnswerGPR));
-    m_jit.assembler().sub(quotientThenRemainderGPR, dividendGPR, multiplyAnswerGPR);
-
-    // If the user cares about negative zero, then speculate that we're not about
-    // to produce negative zero.
-    if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
-        // Check that we're not about to create negative zero.
-        JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, dividendGPR, TrustedImm32(0));
-        speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, quotientThenRemainderGPR));
-        numeratorPositive.link(&m_jit);
-    }
-
-    integerResult(quotientThenRemainderGPR, node);
-#else // not architecture that can do integer division
-    // Do this the *safest* way possible: call out to a C function that will do the modulo,
-    // and then attempt to convert back.
-    GPRReg op1GPR = op1.gpr();
-    GPRReg op2GPR = op2.gpr();
-    
-    FPRResult result(this);
-    
-    flushRegisters();
-    callOperation(operationFModOnInts, result.fpr(), op1GPR, op2GPR);
-    
-    FPRTemporary scratch(this);
-    GPRTemporary intResult(this);
-    JITCompiler::JumpList failureCases;
-    m_jit.branchConvertDoubleToInt32(result.fpr(), intResult.gpr(), failureCases, scratch.fpr(), false);
-    speculationCheck(Overflow, JSValueRegs(), 0, failureCases);
-    if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
-        // Check that we're not about to create negative zero.
-        JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1GPR, TrustedImm32(0));
-        speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, intResult.gpr()));
-        numeratorPositive.link(&m_jit);
-    }
-    
-    integerResult(intResult.gpr(), node);
-#endif // CPU(X86) || CPU(X86_64)
-}
-
 void SpeculativeJIT::compileAdd(Node* node)
 {
     switch (node->binaryUseKind()) {
@@ -3341,128 +3149,350 @@
     }
 }
 
+void SpeculativeJIT::compileArithDiv(Node* node)
+{
+    switch (node->binaryUseKind()) {
+    case Int32Use: {
 #if CPU(X86) || CPU(X86_64)
-void SpeculativeJIT::compileIntegerArithDivForX86(Node* node)
-{
-    SpeculateIntegerOperand op1(this, node->child1());
-    SpeculateIntegerOperand op2(this, node->child2());
-    GPRTemporary eax(this, X86Registers::eax);
-    GPRTemporary edx(this, X86Registers::edx);
-    GPRReg op1GPR = op1.gpr();
-    GPRReg op2GPR = op2.gpr();
+        SpeculateIntegerOperand op1(this, node->child1());
+        SpeculateIntegerOperand op2(this, node->child2());
+        GPRTemporary eax(this, X86Registers::eax);
+        GPRTemporary edx(this, X86Registers::edx);
+        GPRReg op1GPR = op1.gpr();
+        GPRReg op2GPR = op2.gpr();
     
-    GPRReg op2TempGPR;
-    GPRReg temp;
-    if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
-        op2TempGPR = allocate();
-        temp = op2TempGPR;
-    } else {
-        op2TempGPR = InvalidGPRReg;
-        if (op1GPR == X86Registers::eax)
-            temp = X86Registers::edx;
-        else
-            temp = X86Registers::eax;
-    }
+        GPRReg op2TempGPR;
+        GPRReg temp;
+        if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
+            op2TempGPR = allocate();
+            temp = op2TempGPR;
+        } else {
+            op2TempGPR = InvalidGPRReg;
+            if (op1GPR == X86Registers::eax)
+                temp = X86Registers::edx;
+            else
+                temp = X86Registers::eax;
+        }
     
-    ASSERT(temp != op1GPR);
-    ASSERT(temp != op2GPR);
+        ASSERT(temp != op1GPR);
+        ASSERT(temp != op2GPR);
     
-    m_jit.add32(JITCompiler::TrustedImm32(1), op2GPR, temp);
+        m_jit.add32(JITCompiler::TrustedImm32(1), op2GPR, temp);
     
-    JITCompiler::Jump safeDenominator = m_jit.branch32(JITCompiler::Above, temp, JITCompiler::TrustedImm32(1));
+        JITCompiler::Jump safeDenominator = m_jit.branch32(JITCompiler::Above, temp, JITCompiler::TrustedImm32(1));
     
-    JITCompiler::JumpList done;
-    if (nodeUsedAsNumber(node->arithNodeFlags())) {
-        speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, op2GPR));
-        speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1)));
-    } else {
-        // This is the case where we convert the result to an int after we're done, and we
-        // already know that the denominator is either -1 or 0. So, if the denominator is
-        // zero, then the result should be zero. If the denominator is not zero (i.e. it's
-        // -1) and the numerator is -2^31 then the result should be -2^31. Otherwise we
-        // are happy to fall through to a normal division, since we're just dividing
-        // something by negative 1.
+        JITCompiler::JumpList done;
+        if (nodeUsedAsNumber(node->arithNodeFlags())) {
+            speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, op2GPR));
+            speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1)));
+        } else {
+            // This is the case where we convert the result to an int after we're done, and we
+            // already know that the denominator is either -1 or 0. So, if the denominator is
+            // zero, then the result should be zero. If the denominator is not zero (i.e. it's
+            // -1) and the numerator is -2^31 then the result should be -2^31. Otherwise we
+            // are happy to fall through to a normal division, since we're just dividing
+            // something by negative 1.
         
-        JITCompiler::Jump notZero = m_jit.branchTest32(JITCompiler::NonZero, op2GPR);
-        m_jit.move(TrustedImm32(0), eax.gpr());
-        done.append(m_jit.jump());
+            JITCompiler::Jump notZero = m_jit.branchTest32(JITCompiler::NonZero, op2GPR);
+            m_jit.move(TrustedImm32(0), eax.gpr());
+            done.append(m_jit.jump());
         
-        notZero.link(&m_jit);
-        JITCompiler::Jump notNeg2ToThe31 =
-            m_jit.branch32(JITCompiler::NotEqual, op1GPR, TrustedImm32(-2147483647-1));
+            notZero.link(&m_jit);
+            JITCompiler::Jump notNeg2ToThe31 =
+                m_jit.branch32(JITCompiler::NotEqual, op1GPR, TrustedImm32(-2147483647-1));
+            m_jit.move(op1GPR, eax.gpr());
+            done.append(m_jit.jump());
+        
+            notNeg2ToThe31.link(&m_jit);
+        }
+    
+        safeDenominator.link(&m_jit);
+    
+        // If the user cares about negative zero, then speculate that we're not about
+        // to produce negative zero.
+        if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
+            MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR);
+            speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0)));
+            numeratorNonZero.link(&m_jit);
+        }
+    
+        if (op2TempGPR != InvalidGPRReg) {
+            m_jit.move(op2GPR, op2TempGPR);
+            op2GPR = op2TempGPR;
+        }
+            
         m_jit.move(op1GPR, eax.gpr());
-        done.append(m_jit.jump());
-        
-        notNeg2ToThe31.link(&m_jit);
-    }
-    
-    safeDenominator.link(&m_jit);
-    
-    // If the user cares about negative zero, then speculate that we're not about
-    // to produce negative zero.
-    if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
-        MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR);
-        speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0)));
-        numeratorNonZero.link(&m_jit);
-    }
-    
-    if (op2TempGPR != InvalidGPRReg) {
-        m_jit.move(op2GPR, op2TempGPR);
-        op2GPR = op2TempGPR;
-    }
+        m_jit.assembler().cdq();
+        m_jit.assembler().idivl_r(op2GPR);
             
-    m_jit.move(op1GPR, eax.gpr());
-    m_jit.assembler().cdq();
-    m_jit.assembler().idivl_r(op2GPR);
-            
-    if (op2TempGPR != InvalidGPRReg)
-        unlock(op2TempGPR);
+        if (op2TempGPR != InvalidGPRReg)
+            unlock(op2TempGPR);
 
-    // Check that there was no remainder. If there had been, then we'd be obligated to
-    // produce a double result instead.
-    if (nodeUsedAsNumber(node->arithNodeFlags()))
-        speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::NonZero, edx.gpr()));
-    else
-        done.link(&m_jit);
+        // Check that there was no remainder. If there had been, then we'd be obligated to
+        // produce a double result instead.
+        if (nodeUsedAsNumber(node->arithNodeFlags()))
+            speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::NonZero, edx.gpr()));
+        else
+            done.link(&m_jit);
             
-    integerResult(eax.gpr(), node);
-}
+        integerResult(eax.gpr(), node);
 #elif CPU(APPLE_ARMV7S)
-void SpeculativeJIT::compileIntegerArithDivForARMv7s(Node* node)
-{
-    SpeculateIntegerOperand op1(this, node->child1());
-    SpeculateIntegerOperand op2(this, node->child2());
-    GPRReg op1GPR = op1.gpr();
-    GPRReg op2GPR = op2.gpr();
-    GPRTemporary quotient(this);
-    GPRTemporary multiplyAnswer(this);
+        SpeculateIntegerOperand op1(this, node->child1());
+        SpeculateIntegerOperand op2(this, node->child2());
+        GPRReg op1GPR = op1.gpr();
+        GPRReg op2GPR = op2.gpr();
+        GPRTemporary quotient(this);
+        GPRTemporary multiplyAnswer(this);
 
-    // If the user cares about negative zero, then speculate that we're not about
-    // to produce negative zero.
-    if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
-        MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR);
-        speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0)));
-        numeratorNonZero.link(&m_jit);
-    }
+        // If the user cares about negative zero, then speculate that we're not about
+        // to produce negative zero.
+        if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
+            MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR);
+            speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0)));
+            numeratorNonZero.link(&m_jit);
+        }
 
-    m_jit.assembler().sdiv(quotient.gpr(), op1GPR, op2GPR);
+        m_jit.assembler().sdiv(quotient.gpr(), op1GPR, op2GPR);
 
-    // Check that there was no remainder. If there had been, then we'd be obligated to
-    // produce a double result instead.
-    if (nodeUsedAsNumber(node->arithNodeFlags())) {
-        speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchMul32(JITCompiler::Overflow, quotient.gpr(), op2GPR, multiplyAnswer.gpr()));
-        speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(JITCompiler::NotEqual, multiplyAnswer.gpr(), op1GPR));
-    }
+        // Check that there was no remainder. If there had been, then we'd be obligated to
+        // produce a double result instead.
+        if (nodeUsedAsNumber(node->arithNodeFlags())) {
+            speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchMul32(JITCompiler::Overflow, quotient.gpr(), op2GPR, multiplyAnswer.gpr()));
+            speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(JITCompiler::NotEqual, multiplyAnswer.gpr(), op1GPR));
+        }
 
-    integerResult(quotient.gpr(), node);
-}
+        integerResult(quotient.gpr(), node);
+#else
+        RELEASE_ASSERT_NOT_REACHED();
 #endif
+        break;
+    }
+        
+    case NumberUse: {
+        SpeculateDoubleOperand op1(this, node->child1());
+        SpeculateDoubleOperand op2(this, node->child2());
+        FPRTemporary result(this, op1);
+        
+        FPRReg reg1 = op1.fpr();
+        FPRReg reg2 = op2.fpr();
+        m_jit.divDouble(reg1, reg2, result.fpr());
+        
+        doubleResult(result.fpr(), node);
+        break;
+    }
+        
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+        break;
+    }
+}
 
 void SpeculativeJIT::compileArithMod(Node* node)
 {
     switch (node->binaryUseKind()) {
     case Int32Use: {
-        compileSoftModulo(node);
+        // In the fast path, the dividend value could be the final result
+        // (in case of |dividend| < |divisor|), so we speculate it as strict int32.
+        SpeculateStrictInt32Operand op1(this, node->child1());
+        
+        if (isInt32Constant(node->child2().node())) {
+            int32_t divisor = valueOfInt32Constant(node->child2().node());
+            if (divisor > 0 && hasOneBitSet(divisor)) {
+                ASSERT(divisor != 1);
+                unsigned logarithm = WTF::fastLog2(divisor);
+                GPRReg dividendGPR = op1.gpr();
+                GPRTemporary result(this);
+                GPRReg resultGPR = result.gpr();
+
+                // This is what LLVM generates. It's pretty crazy. Here's my
+                // attempt at understanding it.
+                
+                // First, compute either divisor - 1, or 0, depending on whether
+                // the dividend is negative:
+                //
+                // If dividend < 0:  resultGPR = divisor - 1
+                // If dividend >= 0: resultGPR = 0
+                m_jit.move(dividendGPR, resultGPR);
+                m_jit.rshift32(TrustedImm32(31), resultGPR);
+                m_jit.urshift32(TrustedImm32(32 - logarithm), resultGPR);
+                
+                // Add in the dividend, so that:
+                //
+                // If dividend < 0:  resultGPR = dividend + divisor - 1
+                // If dividend >= 0: resultGPR = dividend
+                m_jit.add32(dividendGPR, resultGPR);
+                
+                // Mask so as to only get the *high* bits. This rounds down
+                // (towards negative infinity) resultGPR to the nearest multiple
+                // of divisor, so that:
+                //
+                // If dividend < 0:  resultGPR = floor((dividend + divisor - 1) / divisor)
+                // If dividend >= 0: resultGPR = floor(dividend / divisor)
+                //
+                // Note that this can be simplified to:
+                //
+                // If dividend < 0:  resultGPR = ceil(dividend / divisor)
+                // If dividend >= 0: resultGPR = floor(dividend / divisor)
+                //
+                // Note that if the dividend is negative, resultGPR will also be negative.
+                // Regardless of the sign of dividend, resultGPR will be rounded towards
+                // zero, because of how things are conditionalized.
+                m_jit.and32(TrustedImm32(-divisor), resultGPR);
+                
+                // Subtract resultGPR from dividendGPR, which yields the remainder:
+                //
+                // resultGPR = dividendGPR - resultGPR
+                m_jit.neg32(resultGPR);
+                m_jit.add32(dividendGPR, resultGPR);
+                
+                if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
+                    // Check that we're not about to create negative zero.
+                    JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, dividendGPR, TrustedImm32(0));
+                    speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, resultGPR));
+                    numeratorPositive.link(&m_jit);
+                }
+
+                integerResult(resultGPR, node);
+                return;
+            }
+        }
+        
+#if CPU(X86) || CPU(X86_64)
+        if (isInt32Constant(node->child2().node())) {
+            int32_t divisor = valueOfInt32Constant(node->child2().node());
+            if (divisor) {
+                GPRReg op1Gpr = op1.gpr();
+
+                GPRTemporary eax(this, X86Registers::eax);
+                GPRTemporary edx(this, X86Registers::edx);
+                GPRTemporary scratch(this);
+                GPRReg scratchGPR = scratch.gpr();
+
+                GPRReg op1SaveGPR;
+                if (op1Gpr == X86Registers::eax || op1Gpr == X86Registers::edx) {
+                    op1SaveGPR = allocate();
+                    ASSERT(op1Gpr != op1SaveGPR);
+                    m_jit.move(op1Gpr, op1SaveGPR);
+                } else
+                    op1SaveGPR = op1Gpr;
+                ASSERT(op1SaveGPR != X86Registers::eax);
+                ASSERT(op1SaveGPR != X86Registers::edx);
+
+                m_jit.move(op1Gpr, eax.gpr());
+                m_jit.move(TrustedImm32(divisor), scratchGPR);
+                if (divisor == -1)
+                    speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(JITCompiler::Equal, eax.gpr(), TrustedImm32(-2147483647-1)));
+                m_jit.assembler().cdq();
+                m_jit.assembler().idivl_r(scratchGPR);
+                // Check that we're not about to create negative zero.
+                // FIXME: if the node use doesn't care about neg zero, we can do this more easily.
+                JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
+                speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
+                numeratorPositive.link(&m_jit);
+            
+                if (op1SaveGPR != op1Gpr)
+                    unlock(op1SaveGPR);
+
+                integerResult(edx.gpr(), node);
+                return;
+            }
+        }
+#endif
+
+        SpeculateIntegerOperand op2(this, node->child2());
+#if CPU(X86) || CPU(X86_64)
+        GPRTemporary eax(this, X86Registers::eax);
+        GPRTemporary edx(this, X86Registers::edx);
+        GPRReg op1GPR = op1.gpr();
+        GPRReg op2GPR = op2.gpr();
+    
+        GPRReg op2TempGPR;
+        GPRReg temp;
+        GPRReg op1SaveGPR;
+    
+        if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
+            op2TempGPR = allocate();
+            temp = op2TempGPR;
+        } else {
+            op2TempGPR = InvalidGPRReg;
+            if (op1GPR == X86Registers::eax)
+                temp = X86Registers::edx;
+            else
+                temp = X86Registers::eax;
+        }
+    
+        if (op1GPR == X86Registers::eax || op1GPR == X86Registers::edx) {
+            op1SaveGPR = allocate();
+            ASSERT(op1GPR != op1SaveGPR);
+            m_jit.move(op1GPR, op1SaveGPR);
+        } else
+            op1SaveGPR = op1GPR;
+    
+        ASSERT(temp != op1GPR);
+        ASSERT(temp != op2GPR);
+        ASSERT(op1SaveGPR != X86Registers::eax);
+        ASSERT(op1SaveGPR != X86Registers::edx);
+    
+        m_jit.add32(JITCompiler::TrustedImm32(1), op2GPR, temp);
+    
+        JITCompiler::Jump safeDenominator = m_jit.branch32(JITCompiler::Above, temp, JITCompiler::TrustedImm32(1));
+    
+        JITCompiler::Jump done;
+        // FIXME: if the node is not used as number then we can do this more easily.
+        speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, op2GPR));
+        speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1)));
+    
+        safeDenominator.link(&m_jit);
+            
+        if (op2TempGPR != InvalidGPRReg) {
+            m_jit.move(op2GPR, op2TempGPR);
+            op2GPR = op2TempGPR;
+        }
+            
+        m_jit.move(op1GPR, eax.gpr());
+        m_jit.assembler().cdq();
+        m_jit.assembler().idivl_r(op2GPR);
+            
+        if (op2TempGPR != InvalidGPRReg)
+            unlock(op2TempGPR);
+
+        // Check that we're not about to create negative zero.
+        // FIXME: if the node use doesn't care about neg zero, we can do this more easily.
+        JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
+        speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
+        numeratorPositive.link(&m_jit);
+    
+        if (op1SaveGPR != op1GPR)
+            unlock(op1SaveGPR);
+            
+        integerResult(edx.gpr(), node);
+
+#elif CPU(APPLE_ARMV7S)
+        GPRTemporary temp(this);
+        GPRTemporary quotientThenRemainder(this);
+        GPRTemporary multiplyAnswer(this);
+        GPRReg dividendGPR = op1.gpr();
+        GPRReg divisorGPR = op2.gpr();
+        GPRReg quotientThenRemainderGPR = quotientThenRemainder.gpr();
+        GPRReg multiplyAnswerGPR = multiplyAnswer.gpr();
+
+        m_jit.assembler().sdiv(quotientThenRemainderGPR, dividendGPR, divisorGPR);
+        speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchMul32(JITCompiler::Overflow, quotientThenRemainderGPR, divisorGPR, multiplyAnswerGPR));
+        m_jit.assembler().sub(quotientThenRemainderGPR, dividendGPR, multiplyAnswerGPR);
+
+        // If the user cares about negative zero, then speculate that we're not about
+        // to produce negative zero.
+        if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
+            // Check that we're not about to create negative zero.
+            JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, dividendGPR, TrustedImm32(0));
+            speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, quotientThenRemainderGPR));
+            numeratorPositive.link(&m_jit);
+        }
+
+        integerResult(quotientThenRemainderGPR, node);
+#else // not architecture that can do integer division
+        RELEASE_ASSERT_NOT_REACHED();
+#endif
         return;
     }
         
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index 610bf84..bb2aa10 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -1998,13 +1998,8 @@
     void compileArithNegate(Node*);
     void compileArithMul(Node*);
     void compileArithIMul(Node*);
-#if CPU(X86) || CPU(X86_64)
-    void compileIntegerArithDivForX86(Node*);
-#elif CPU(APPLE_ARMV7S)
-    void compileIntegerArithDivForARMv7s(Node*);
-#endif
+    void compileArithDiv(Node*);
     void compileArithMod(Node*);
-    void compileSoftModulo(Node*);
     void compileGetIndexedPropertyStorage(Node*);
     void compileGetByValOnIntTypedArray(const TypedArrayDescriptor&, Node*, size_t elementSize, TypedArraySignedness);
     void compilePutByValForIntTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node*, size_t elementSize, TypedArraySignedness, TypedArrayRounding = TruncateRounding);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index 763b0cc..eea66e9 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -2251,35 +2251,7 @@
         break;
 
     case ArithDiv: {
-        switch (node->binaryUseKind()) {
-        case Int32Use: {
-#if CPU(X86)
-            compileIntegerArithDivForX86(node);
-#elif CPU(APPLE_ARMV7S)
-            compileIntegerArithDivForARMv7s(node);
-#else // CPU type without integer divide
-            RELEASE_ASSERT_NOT_REACHED(); // should have been coverted into a double divide.
-#endif
-            break;
-        }
-            
-        case NumberUse: {
-            SpeculateDoubleOperand op1(this, node->child1());
-            SpeculateDoubleOperand op2(this, node->child2());
-            FPRTemporary result(this, op1);
-            
-            FPRReg reg1 = op1.fpr();
-            FPRReg reg2 = op2.fpr();
-            m_jit.divDouble(reg1, reg2, result.fpr());
-            
-            doubleResult(result.fpr(), node);
-            break;
-        }
-            
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-            break;
-        }
+        compileArithDiv(node);
         break;
     }
 
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 747f7d8..508c1af 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -2192,29 +2192,7 @@
         break;
 
     case ArithDiv: {
-        switch (node->binaryUseKind()) {
-        case Int32Use: {
-            compileIntegerArithDivForX86(node);
-            break;
-        }
-            
-        case NumberUse: {
-            SpeculateDoubleOperand op1(this, node->child1());
-            SpeculateDoubleOperand op2(this, node->child2());
-            FPRTemporary result(this, op1);
-            
-            FPRReg reg1 = op1.fpr();
-            FPRReg reg2 = op2.fpr();
-            m_jit.divDouble(reg1, reg2, result.fpr());
-            
-            doubleResult(result.fpr(), node);
-            break;
-        }
-            
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-            break;
-        }
+        compileArithDiv(node);
         break;
     }