Bug 1201810, IonMonkey - Part 1: Move the platform specific shared ic stubs, r=jandem
authorHannes Verschore <hv1989@gmail.com>
Thu, 10 Sep 2015 14:02:22 +0200
changeset 296079 8d7edac29dad30794d96fa21445ccb4d43a5c952
parent 296078 01324f0b7651c258bb903becbc8484c9a7ecbd13
child 296080 a1255d7b2c115f59f0ff0e3f698464b0a1ddc6e6
push id962
push userjlund@mozilla.com
push dateFri, 04 Dec 2015 23:28:54 +0000
treeherdermozilla-release@23a2d286e80f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1201810
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1201810, IonMonkey - Part 1: Move the platform specific shared ic stubs, r=jandem
js/src/jit/arm/BaselineIC-arm.cpp
js/src/jit/arm/SharedIC-arm.cpp
js/src/jit/arm64/BaselineIC-arm64.cpp
js/src/jit/arm64/SharedIC-arm64.cpp
js/src/jit/mips32/BaselineIC-mips32.cpp
js/src/jit/mips32/SharedIC-mips32.cpp
js/src/jit/x64/BaselineIC-x64.cpp
js/src/jit/x64/SharedIC-x64.cpp
js/src/jit/x86/BaselineIC-x86.cpp
js/src/jit/x86/SharedIC-x86.cpp
js/src/moz.build
--- a/js/src/jit/arm/BaselineIC-arm.cpp
+++ b/js/src/jit/arm/BaselineIC-arm.cpp
@@ -65,201 +65,10 @@ ICCompare_Double::Compiler::generateStub
     EmitReturnFromIC(masm);
 
     // Failure case - jump to next stub.
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
     return true;
 }
 
-// ICBinaryArith_Int32
-
-extern "C" {
-    extern MOZ_EXPORT int64_t __aeabi_idivmod(int,int);
-}
-
-bool
-ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
-{
-    // Guard that R0 is an integer and R1 is an integer.
-    Label failure;
-    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
-    masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
-
-    // Add R0 and R1. Don't need to explicitly unbox, just use R2's payloadReg.
-    Register scratchReg = R2.payloadReg();
-
-    // DIV and MOD need an extra non-volatile ValueOperand to hold R0.
-    AllocatableGeneralRegisterSet savedRegs(availableGeneralRegs(2));
-    savedRegs.set() = GeneralRegisterSet::Intersect(GeneralRegisterSet::NonVolatile(), savedRegs.set());
-    ValueOperand savedValue = savedRegs.takeAnyValue();
-
-    Label maybeNegZero, revertRegister;
-    switch(op_) {
-      case JSOP_ADD:
-        masm.ma_add(R0.payloadReg(), R1.payloadReg(), scratchReg, SetCC);
-
-        // Just jump to failure on overflow. R0 and R1 are preserved, so we can
-        // just jump to the next stub.
-        masm.j(Assembler::Overflow, &failure);
-
-        // Box the result and return. We know R0.typeReg() already contains the
-        // integer tag, so we just need to move the result value into place.
-        masm.mov(scratchReg, R0.payloadReg());
-        break;
-      case JSOP_SUB:
-        masm.ma_sub(R0.payloadReg(), R1.payloadReg(), scratchReg, SetCC);
-        masm.j(Assembler::Overflow, &failure);
-        masm.mov(scratchReg, R0.payloadReg());
-        break;
-      case JSOP_MUL: {
-        Assembler::Condition cond = masm.ma_check_mul(R0.payloadReg(), R1.payloadReg(), scratchReg,
-                                                      Assembler::Overflow);
-        masm.j(cond, &failure);
-
-        masm.ma_cmp(scratchReg, Imm32(0));
-        masm.j(Assembler::Equal, &maybeNegZero);
-
-        masm.mov(scratchReg, R0.payloadReg());
-        break;
-      }
-      case JSOP_DIV:
-      case JSOP_MOD: {
-        // Check for INT_MIN / -1, it results in a double.
-        masm.ma_cmp(R0.payloadReg(), Imm32(INT_MIN));
-        masm.ma_cmp(R1.payloadReg(), Imm32(-1), Assembler::Equal);
-        masm.j(Assembler::Equal, &failure);
-
-        // Check for both division by zero and 0 / X with X < 0 (results in -0).
-        masm.ma_cmp(R1.payloadReg(), Imm32(0));
-        masm.ma_cmp(R0.payloadReg(), Imm32(0), Assembler::LessThan);
-        masm.j(Assembler::Equal, &failure);
-
-        // The call will preserve registers r4-r11. Save R0 and the link
-        // register.
-        MOZ_ASSERT(R1 == ValueOperand(r5, r4));
-        MOZ_ASSERT(R0 == ValueOperand(r3, r2));
-        masm.moveValue(R0, savedValue);
-
-        masm.setupAlignedABICall();
-        masm.passABIArg(R0.payloadReg());
-        masm.passABIArg(R1.payloadReg());
-        masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, __aeabi_idivmod));
-
-        // idivmod returns the quotient in r0, and the remainder in r1.
-        if (op_ == JSOP_DIV) {
-            // Result is a double if the remainder != 0.
-            masm.branch32(Assembler::NotEqual, r1, Imm32(0), &revertRegister);
-            masm.tagValue(JSVAL_TYPE_INT32, r0, R0);
-        } else {
-            // If X % Y == 0 and X < 0, the result is -0.
-            Label done;
-            masm.branch32(Assembler::NotEqual, r1, Imm32(0), &done);
-            masm.branch32(Assembler::LessThan, savedValue.payloadReg(), Imm32(0), &revertRegister);
-            masm.bind(&done);
-            masm.tagValue(JSVAL_TYPE_INT32, r1, R0);
-        }
-        break;
-      }
-      case JSOP_BITOR:
-        masm.ma_orr(R1.payloadReg(), R0.payloadReg(), R0.payloadReg());
-        break;
-      case JSOP_BITXOR:
-        masm.ma_eor(R1.payloadReg(), R0.payloadReg(), R0.payloadReg());
-        break;
-      case JSOP_BITAND:
-        masm.ma_and(R1.payloadReg(), R0.payloadReg(), R0.payloadReg());
-        break;
-      case JSOP_LSH:
-        // ARM will happily try to shift by more than 0x1f.
-        masm.ma_and(Imm32(0x1F), R1.payloadReg(), R1.payloadReg());
-        masm.ma_lsl(R1.payloadReg(), R0.payloadReg(), R0.payloadReg());
-        break;
-      case JSOP_RSH:
-        masm.ma_and(Imm32(0x1F), R1.payloadReg(), R1.payloadReg());
-        masm.ma_asr(R1.payloadReg(), R0.payloadReg(), R0.payloadReg());
-        break;
-      case JSOP_URSH:
-        masm.ma_and(Imm32(0x1F), R1.payloadReg(), scratchReg);
-        masm.ma_lsr(scratchReg, R0.payloadReg(), scratchReg);
-        masm.ma_cmp(scratchReg, Imm32(0));
-        if (allowDouble_) {
-            Label toUint;
-            masm.j(Assembler::LessThan, &toUint);
-
-            // Move result and box for return.
-            masm.mov(scratchReg, R0.payloadReg());
-            EmitReturnFromIC(masm);
-
-            masm.bind(&toUint);
-            ScratchDoubleScope scratchDouble(masm);
-            masm.convertUInt32ToDouble(scratchReg, scratchDouble);
-            masm.boxDouble(scratchDouble, R0);
-        } else {
-            masm.j(Assembler::LessThan, &failure);
-            // Move result for return.
-            masm.mov(scratchReg, R0.payloadReg());
-        }
-        break;
-      default:
-        MOZ_CRASH("Unhandled op for BinaryArith_Int32.");
-    }
-
-    EmitReturnFromIC(masm);
-
-    switch (op_) {
-      case JSOP_MUL:
-        masm.bind(&maybeNegZero);
-
-        // Result is -0 if exactly one of lhs or rhs is negative.
-        masm.ma_cmn(R0.payloadReg(), R1.payloadReg());
-        masm.j(Assembler::Signed, &failure);
-
-        // Result is +0.
-        masm.ma_mov(Imm32(0), R0.payloadReg());
-        EmitReturnFromIC(masm);
-        break;
-      case JSOP_DIV:
-      case JSOP_MOD:
-        masm.bind(&revertRegister);
-        masm.moveValue(savedValue, R0);
-        break;
-      default:
-        break;
-    }
-
-    // Failure case - jump to next stub.
-    masm.bind(&failure);
-    EmitStubGuardFailure(masm);
-
-    return true;
-}
-
-bool
-ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
-{
-    Label failure;
-    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
-
-    switch (op) {
-      case JSOP_BITNOT:
-        masm.ma_mvn(R0.payloadReg(), R0.payloadReg());
-        break;
-      case JSOP_NEG:
-        // Guard against 0 and MIN_INT, both result in a double.
-        masm.branchTest32(Assembler::Zero, R0.payloadReg(), Imm32(0x7fffffff), &failure);
-
-        // Compile -x as 0 - x.
-        masm.ma_rsb(R0.payloadReg(), Imm32(0), R0.payloadReg());
-        break;
-      default:
-        MOZ_CRASH("Unexpected op");
-    }
-
-    EmitReturnFromIC(masm);
-
-    masm.bind(&failure);
-    EmitStubGuardFailure(masm);
-    return true;
-}
-
 } // namespace jit
 } // namespace js
new file mode 100644
--- /dev/null
+++ b/js/src/jit/arm/SharedIC-arm.cpp
@@ -0,0 +1,213 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * 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 "jit/BaselineCompiler.h"
+#include "jit/BaselineIC.h"
+#include "jit/BaselineJIT.h"
+#include "jit/Linker.h"
+#include "jit/SharedICHelpers.h"
+
+#include "jit/MacroAssembler-inl.h"
+
+using namespace js;
+using namespace js::jit;
+
+namespace js {
+namespace jit {
+
+// ICBinaryArith_Int32
+
+extern "C" {
+    extern MOZ_EXPORT int64_t __aeabi_idivmod(int,int);
+}
+
+bool
+ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
+{
+    // Guard that R0 is an integer and R1 is an integer.
+    Label failure;
+    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
+    masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
+
+    // Add R0 and R1. Don't need to explicitly unbox, just use R2's payloadReg.
+    Register scratchReg = R2.payloadReg();
+
+    // DIV and MOD need an extra non-volatile ValueOperand to hold R0.
+    AllocatableGeneralRegisterSet savedRegs(availableGeneralRegs(2));
+    savedRegs.set() = GeneralRegisterSet::Intersect(GeneralRegisterSet::NonVolatile(), savedRegs.set());
+    ValueOperand savedValue = savedRegs.takeAnyValue();
+
+    Label maybeNegZero, revertRegister;
+    switch(op_) {
+      case JSOP_ADD:
+        masm.ma_add(R0.payloadReg(), R1.payloadReg(), scratchReg, SetCC);
+
+        // Just jump to failure on overflow. R0 and R1 are preserved, so we can
+        // just jump to the next stub.
+        masm.j(Assembler::Overflow, &failure);
+
+        // Box the result and return. We know R0.typeReg() already contains the
+        // integer tag, so we just need to move the result value into place.
+        masm.mov(scratchReg, R0.payloadReg());
+        break;
+      case JSOP_SUB:
+        masm.ma_sub(R0.payloadReg(), R1.payloadReg(), scratchReg, SetCC);
+        masm.j(Assembler::Overflow, &failure);
+        masm.mov(scratchReg, R0.payloadReg());
+        break;
+      case JSOP_MUL: {
+        Assembler::Condition cond = masm.ma_check_mul(R0.payloadReg(), R1.payloadReg(), scratchReg,
+                                                      Assembler::Overflow);
+        masm.j(cond, &failure);
+
+        masm.ma_cmp(scratchReg, Imm32(0));
+        masm.j(Assembler::Equal, &maybeNegZero);
+
+        masm.mov(scratchReg, R0.payloadReg());
+        break;
+      }
+      case JSOP_DIV:
+      case JSOP_MOD: {
+        // Check for INT_MIN / -1, it results in a double.
+        masm.ma_cmp(R0.payloadReg(), Imm32(INT_MIN));
+        masm.ma_cmp(R1.payloadReg(), Imm32(-1), Assembler::Equal);
+        masm.j(Assembler::Equal, &failure);
+
+        // Check for both division by zero and 0 / X with X < 0 (results in -0).
+        masm.ma_cmp(R1.payloadReg(), Imm32(0));
+        masm.ma_cmp(R0.payloadReg(), Imm32(0), Assembler::LessThan);
+        masm.j(Assembler::Equal, &failure);
+
+        // The call will preserve registers r4-r11. Save R0 and the link
+        // register.
+        MOZ_ASSERT(R1 == ValueOperand(r5, r4));
+        MOZ_ASSERT(R0 == ValueOperand(r3, r2));
+        masm.moveValue(R0, savedValue);
+
+        masm.setupAlignedABICall();
+        masm.passABIArg(R0.payloadReg());
+        masm.passABIArg(R1.payloadReg());
+        masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, __aeabi_idivmod));
+
+        // idivmod returns the quotient in r0, and the remainder in r1.
+        if (op_ == JSOP_DIV) {
+            // Result is a double if the remainder != 0.
+            masm.branch32(Assembler::NotEqual, r1, Imm32(0), &revertRegister);
+            masm.tagValue(JSVAL_TYPE_INT32, r0, R0);
+        } else {
+            // If X % Y == 0 and X < 0, the result is -0.
+            Label done;
+            masm.branch32(Assembler::NotEqual, r1, Imm32(0), &done);
+            masm.branch32(Assembler::LessThan, savedValue.payloadReg(), Imm32(0), &revertRegister);
+            masm.bind(&done);
+            masm.tagValue(JSVAL_TYPE_INT32, r1, R0);
+        }
+        break;
+      }
+      case JSOP_BITOR:
+        masm.ma_orr(R1.payloadReg(), R0.payloadReg(), R0.payloadReg());
+        break;
+      case JSOP_BITXOR:
+        masm.ma_eor(R1.payloadReg(), R0.payloadReg(), R0.payloadReg());
+        break;
+      case JSOP_BITAND:
+        masm.ma_and(R1.payloadReg(), R0.payloadReg(), R0.payloadReg());
+        break;
+      case JSOP_LSH:
+        // ARM will happily try to shift by more than 0x1f.
+        masm.ma_and(Imm32(0x1F), R1.payloadReg(), R1.payloadReg());
+        masm.ma_lsl(R1.payloadReg(), R0.payloadReg(), R0.payloadReg());
+        break;
+      case JSOP_RSH:
+        masm.ma_and(Imm32(0x1F), R1.payloadReg(), R1.payloadReg());
+        masm.ma_asr(R1.payloadReg(), R0.payloadReg(), R0.payloadReg());
+        break;
+      case JSOP_URSH:
+        masm.ma_and(Imm32(0x1F), R1.payloadReg(), scratchReg);
+        masm.ma_lsr(scratchReg, R0.payloadReg(), scratchReg);
+        masm.ma_cmp(scratchReg, Imm32(0));
+        if (allowDouble_) {
+            Label toUint;
+            masm.j(Assembler::LessThan, &toUint);
+
+            // Move result and box for return.
+            masm.mov(scratchReg, R0.payloadReg());
+            EmitReturnFromIC(masm);
+
+            masm.bind(&toUint);
+            ScratchDoubleScope scratchDouble(masm);
+            masm.convertUInt32ToDouble(scratchReg, scratchDouble);
+            masm.boxDouble(scratchDouble, R0);
+        } else {
+            masm.j(Assembler::LessThan, &failure);
+            // Move result for return.
+            masm.mov(scratchReg, R0.payloadReg());
+        }
+        break;
+      default:
+        MOZ_CRASH("Unhandled op for BinaryArith_Int32.");
+    }
+
+    EmitReturnFromIC(masm);
+
+    switch (op_) {
+      case JSOP_MUL:
+        masm.bind(&maybeNegZero);
+
+        // Result is -0 if exactly one of lhs or rhs is negative.
+        masm.ma_cmn(R0.payloadReg(), R1.payloadReg());
+        masm.j(Assembler::Signed, &failure);
+
+        // Result is +0.
+        masm.ma_mov(Imm32(0), R0.payloadReg());
+        EmitReturnFromIC(masm);
+        break;
+      case JSOP_DIV:
+      case JSOP_MOD:
+        masm.bind(&revertRegister);
+        masm.moveValue(savedValue, R0);
+        break;
+      default:
+        break;
+    }
+
+    // Failure case - jump to next stub.
+    masm.bind(&failure);
+    EmitStubGuardFailure(masm);
+
+    return true;
+}
+
+bool
+ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
+{
+    Label failure;
+    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
+
+    switch (op) {
+      case JSOP_BITNOT:
+        masm.ma_mvn(R0.payloadReg(), R0.payloadReg());
+        break;
+      case JSOP_NEG:
+        // Guard against 0 and MIN_INT, both result in a double.
+        masm.branchTest32(Assembler::Zero, R0.payloadReg(), Imm32(0x7fffffff), &failure);
+
+        // Compile -x as 0 - x.
+        masm.ma_rsb(R0.payloadReg(), Imm32(0), R0.payloadReg());
+        break;
+      default:
+        MOZ_CRASH("Unexpected op");
+    }
+
+    EmitReturnFromIC(masm);
+
+    masm.bind(&failure);
+    EmitStubGuardFailure(masm);
+    return true;
+}
+
+} // namespace jit
+} // namespace js
--- a/js/src/jit/arm64/BaselineIC-arm64.cpp
+++ b/js/src/jit/arm64/BaselineIC-arm64.cpp
@@ -65,205 +65,10 @@ ICCompare_Double::Compiler::generateStub
     EmitReturnFromIC(masm);
 
     // Failure case - jump to next stub.
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
     return true;
 }
 
-// ICBinaryArith_Int32
-
-bool
-ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
-{
-    // Guard that R0 is an integer and R1 is an integer.
-    Label failure;
-    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
-    masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
-
-    // Add R0 and R1. Don't need to explicitly unbox, just use R2.
-    Register Rscratch = R2_;
-    ARMRegister Wscratch = ARMRegister(Rscratch, 32);
-#ifdef MERGE
-    // DIV and MOD need an extra non-volatile ValueOperand to hold R0.
-    AllocatableGeneralRegisterSet savedRegs(availableGeneralRegs(2));
-    savedRegs.set() = GeneralRegisterSet::Intersect(GeneralRegisterSet::NonVolatile(), savedRegs);
-#endif
-    // get some more ARM-y names for the registers
-    ARMRegister W0(R0_, 32);
-    ARMRegister X0(R0_, 64);
-    ARMRegister W1(R1_, 32);
-    ARMRegister X1(R1_, 64);
-    ARMRegister WTemp(ExtractTemp0, 32);
-    ARMRegister XTemp(ExtractTemp0, 64);
-    Label maybeNegZero, revertRegister;
-    switch(op_) {
-      case JSOP_ADD:
-        masm.Adds(WTemp, W0, Operand(W1));
-
-        // Just jump to failure on overflow. R0 and R1 are preserved, so we can
-        // just jump to the next stub.
-        masm.j(Assembler::Overflow, &failure);
-
-        // Box the result and return. We know R0 already contains the
-        // integer tag, so we just need to move the payload into place.
-        masm.movePayload(ExtractTemp0, R0_);
-        break;
-
-      case JSOP_SUB:
-        masm.Subs(WTemp, W0, Operand(W1));
-        masm.j(Assembler::Overflow, &failure);
-        masm.movePayload(ExtractTemp0, R0_);
-        break;
-
-      case JSOP_MUL:
-        masm.mul32(R0.valueReg(), R1.valueReg(), Rscratch, &failure, &maybeNegZero);
-        masm.movePayload(Rscratch, R0_);
-        break;
-
-      case JSOP_DIV:
-      case JSOP_MOD: {
-
-        // Check for INT_MIN / -1, it results in a double.
-        Label check2;
-        masm.Cmp(W0, Operand(INT_MIN));
-        masm.B(&check2, Assembler::NotEqual);
-        masm.Cmp(W1, Operand(-1));
-        masm.j(Assembler::Equal, &failure);
-        masm.bind(&check2);
-        Label no_fail;
-        // Check for both division by zero and 0 / X with X < 0 (results in -0).
-        masm.Cmp(W1, Operand(0));
-        // If x > 0, then it can't be bad.
-        masm.B(&no_fail, Assembler::GreaterThan);
-        // if x == 0, then ignore any comparison, and force
-        // it to fail, if x < 0 (the only other case)
-        // then do the comparison, and fail if y == 0
-        masm.Ccmp(W0, Operand(0), vixl::ZFlag, Assembler::NotEqual);
-        masm.B(&failure, Assembler::Equal);
-        masm.bind(&no_fail);
-        masm.Sdiv(Wscratch, W0, W1);
-        // Start calculating the remainder, x - (x / y) * y.
-        masm.mul(WTemp, W1, Wscratch);
-        if (op_ == JSOP_DIV) {
-            // Result is a double if the remainder != 0, which happens
-            // when (x/y)*y != x.
-            masm.branch32(Assembler::NotEqual, R0.valueReg(), ExtractTemp0, &revertRegister);
-            masm.movePayload(Rscratch, R0_);
-        } else {
-            // Calculate the actual mod. Set the condition code, so we can see if it is non-zero.
-            masm.Subs(WTemp, W0, WTemp);
-
-            // If X % Y == 0 and X < 0, the result is -0.
-            masm.Ccmp(W0, Operand(0), vixl::NoFlag, Assembler::Equal);
-            masm.branch(Assembler::LessThan, &revertRegister);
-            masm.movePayload(ExtractTemp0, R0_);
-        }
-        break;
-      }
-        // ORR, EOR, AND can trivially be coerced int
-        // working without affecting the tag of the dest..
-      case JSOP_BITOR:
-        masm.Orr(X0, X0, Operand(X1));
-        break;
-      case JSOP_BITXOR:
-        masm.Eor(X0, X0, Operand(W1, vixl::UXTW));
-        break;
-      case JSOP_BITAND:
-        masm.And(X0, X0, Operand(X1));
-        break;
-        // LSH, RSH and URSH can not.
-      case JSOP_LSH:
-        // ARM will happily try to shift by more than 0x1f.
-        masm.Lsl(Wscratch, W0, W1);
-        masm.movePayload(Rscratch, R0.valueReg());
-        break;
-      case JSOP_RSH:
-        masm.Asr(Wscratch, W0, W1);
-        masm.movePayload(Rscratch, R0.valueReg());
-        break;
-      case JSOP_URSH:
-        masm.Lsr(Wscratch, W0, W1);
-        if (allowDouble_) {
-            Label toUint;
-            // Testing for negative is equivalent to testing bit 31
-            masm.Tbnz(Wscratch, 31, &toUint);
-            // Move result and box for return.
-            masm.movePayload(Rscratch, R0_);
-            EmitReturnFromIC(masm);
-
-            masm.bind(&toUint);
-            masm.convertUInt32ToDouble(Rscratch, ScratchDoubleReg);
-            masm.boxDouble(ScratchDoubleReg, R0);
-        } else {
-            // Testing for negative is equivalent to testing bit 31
-            masm.Tbnz(Wscratch, 31, &failure);
-            // Move result for return.
-            masm.movePayload(Rscratch, R0_);
-        }
-        break;
-      default:
-        MOZ_CRASH("Unhandled op for BinaryArith_Int32.");
-    }
-
-    EmitReturnFromIC(masm);
-
-    switch (op_) {
-      case JSOP_MUL:
-        masm.bind(&maybeNegZero);
-
-        // Result is -0 if exactly one of lhs or rhs is negative.
-        masm.Cmn(W0, W1);
-        masm.j(Assembler::Signed, &failure);
-
-        // Result is +0, so use the zero register.
-        masm.movePayload(rzr, R0_);
-        EmitReturnFromIC(masm);
-        break;
-      case JSOP_DIV:
-      case JSOP_MOD:
-        masm.bind(&revertRegister);
-        break;
-      default:
-        break;
-    }
-
-    // Failure case - jump to next stub.
-    masm.bind(&failure);
-    EmitStubGuardFailure(masm);
-
-    return true;
-}
-
-bool
-ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
-{
-    Label failure;
-    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
-
-    switch (op) {
-      case JSOP_BITNOT:
-        masm.Mvn(ARMRegister(R1.valueReg(), 32), ARMRegister(R0.valueReg(), 32));
-        masm.movePayload(R1.valueReg(), R0.valueReg());
-        break;
-      case JSOP_NEG:
-        // Guard against 0 and MIN_INT, both result in a double.
-        masm.branchTest32(Assembler::Zero, R0.valueReg(), Imm32(0x7fffffff), &failure);
-
-        // Compile -x as 0 - x.
-        masm.Sub(ARMRegister(R1.valueReg(), 32), wzr, ARMRegister(R0.valueReg(), 32));
-        masm.movePayload(R1.valueReg(), R0.valueReg());
-        break;
-      default:
-        MOZ_CRASH("Unexpected op");
-    }
-
-    EmitReturnFromIC(masm);
-
-    masm.bind(&failure);
-    EmitStubGuardFailure(masm);
-    return true;
-
-}
-
 } // namespace jit
 } // namespace js
new file mode 100644
--- /dev/null
+++ b/js/src/jit/arm64/SharedIC-arm64.cpp
@@ -0,0 +1,219 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * 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 "jit/SharedIC.h"
+#include "jit/SharedICHelpers.h"
+
+#ifdef JS_SIMULATOR_ARM64
+#include "jit/arm64/Assembler-arm64.h"
+#include "jit/arm64/BaselineCompiler-arm64.h"
+#include "jit/arm64/vixl/Debugger-vixl.h"
+#endif
+
+
+using namespace js;
+using namespace js::jit;
+
+namespace js {
+namespace jit {
+
+// ICBinaryArith_Int32
+
+bool
+ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
+{
+    // Guard that R0 is an integer and R1 is an integer.
+    Label failure;
+    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
+    masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
+
+    // Add R0 and R1. Don't need to explicitly unbox, just use R2.
+    Register Rscratch = R2_;
+    ARMRegister Wscratch = ARMRegister(Rscratch, 32);
+#ifdef MERGE
+    // DIV and MOD need an extra non-volatile ValueOperand to hold R0.
+    AllocatableGeneralRegisterSet savedRegs(availableGeneralRegs(2));
+    savedRegs.set() = GeneralRegisterSet::Intersect(GeneralRegisterSet::NonVolatile(), savedRegs);
+#endif
+    // get some more ARM-y names for the registers
+    ARMRegister W0(R0_, 32);
+    ARMRegister X0(R0_, 64);
+    ARMRegister W1(R1_, 32);
+    ARMRegister X1(R1_, 64);
+    ARMRegister WTemp(ExtractTemp0, 32);
+    ARMRegister XTemp(ExtractTemp0, 64);
+    Label maybeNegZero, revertRegister;
+    switch(op_) {
+      case JSOP_ADD:
+        masm.Adds(WTemp, W0, Operand(W1));
+
+        // Just jump to failure on overflow. R0 and R1 are preserved, so we can
+        // just jump to the next stub.
+        masm.j(Assembler::Overflow, &failure);
+
+        // Box the result and return. We know R0 already contains the
+        // integer tag, so we just need to move the payload into place.
+        masm.movePayload(ExtractTemp0, R0_);
+        break;
+
+      case JSOP_SUB:
+        masm.Subs(WTemp, W0, Operand(W1));
+        masm.j(Assembler::Overflow, &failure);
+        masm.movePayload(ExtractTemp0, R0_);
+        break;
+
+      case JSOP_MUL:
+        masm.mul32(R0.valueReg(), R1.valueReg(), Rscratch, &failure, &maybeNegZero);
+        masm.movePayload(Rscratch, R0_);
+        break;
+
+      case JSOP_DIV:
+      case JSOP_MOD: {
+
+        // Check for INT_MIN / -1, it results in a double.
+        Label check2;
+        masm.Cmp(W0, Operand(INT_MIN));
+        masm.B(&check2, Assembler::NotEqual);
+        masm.Cmp(W1, Operand(-1));
+        masm.j(Assembler::Equal, &failure);
+        masm.bind(&check2);
+        Label no_fail;
+        // Check for both division by zero and 0 / X with X < 0 (results in -0).
+        masm.Cmp(W1, Operand(0));
+        // If x > 0, then it can't be bad.
+        masm.B(&no_fail, Assembler::GreaterThan);
+        // if x == 0, then ignore any comparison, and force
+        // it to fail, if x < 0 (the only other case)
+        // then do the comparison, and fail if y == 0
+        masm.Ccmp(W0, Operand(0), vixl::ZFlag, Assembler::NotEqual);
+        masm.B(&failure, Assembler::Equal);
+        masm.bind(&no_fail);
+        masm.Sdiv(Wscratch, W0, W1);
+        // Start calculating the remainder, x - (x / y) * y.
+        masm.mul(WTemp, W1, Wscratch);
+        if (op_ == JSOP_DIV) {
+            // Result is a double if the remainder != 0, which happens
+            // when (x/y)*y != x.
+            masm.branch32(Assembler::NotEqual, R0.valueReg(), ExtractTemp0, &revertRegister);
+            masm.movePayload(Rscratch, R0_);
+        } else {
+            // Calculate the actual mod. Set the condition code, so we can see if it is non-zero.
+            masm.Subs(WTemp, W0, WTemp);
+
+            // If X % Y == 0 and X < 0, the result is -0.
+            masm.Ccmp(W0, Operand(0), vixl::NoFlag, Assembler::Equal);
+            masm.branch(Assembler::LessThan, &revertRegister);
+            masm.movePayload(ExtractTemp0, R0_);
+        }
+        break;
+      }
+        // ORR, EOR, AND can trivially be coerced int
+        // working without affecting the tag of the dest..
+      case JSOP_BITOR:
+        masm.Orr(X0, X0, Operand(X1));
+        break;
+      case JSOP_BITXOR:
+        masm.Eor(X0, X0, Operand(W1, vixl::UXTW));
+        break;
+      case JSOP_BITAND:
+        masm.And(X0, X0, Operand(X1));
+        break;
+        // LSH, RSH and URSH can not.
+      case JSOP_LSH:
+        // ARM will happily try to shift by more than 0x1f.
+        masm.Lsl(Wscratch, W0, W1);
+        masm.movePayload(Rscratch, R0.valueReg());
+        break;
+      case JSOP_RSH:
+        masm.Asr(Wscratch, W0, W1);
+        masm.movePayload(Rscratch, R0.valueReg());
+        break;
+      case JSOP_URSH:
+        masm.Lsr(Wscratch, W0, W1);
+        if (allowDouble_) {
+            Label toUint;
+            // Testing for negative is equivalent to testing bit 31
+            masm.Tbnz(Wscratch, 31, &toUint);
+            // Move result and box for return.
+            masm.movePayload(Rscratch, R0_);
+            EmitReturnFromIC(masm);
+
+            masm.bind(&toUint);
+            masm.convertUInt32ToDouble(Rscratch, ScratchDoubleReg);
+            masm.boxDouble(ScratchDoubleReg, R0);
+        } else {
+            // Testing for negative is equivalent to testing bit 31
+            masm.Tbnz(Wscratch, 31, &failure);
+            // Move result for return.
+            masm.movePayload(Rscratch, R0_);
+        }
+        break;
+      default:
+        MOZ_CRASH("Unhandled op for BinaryArith_Int32.");
+    }
+
+    EmitReturnFromIC(masm);
+
+    switch (op_) {
+      case JSOP_MUL:
+        masm.bind(&maybeNegZero);
+
+        // Result is -0 if exactly one of lhs or rhs is negative.
+        masm.Cmn(W0, W1);
+        masm.j(Assembler::Signed, &failure);
+
+        // Result is +0, so use the zero register.
+        masm.movePayload(rzr, R0_);
+        EmitReturnFromIC(masm);
+        break;
+      case JSOP_DIV:
+      case JSOP_MOD:
+        masm.bind(&revertRegister);
+        break;
+      default:
+        break;
+    }
+
+    // Failure case - jump to next stub.
+    masm.bind(&failure);
+    EmitStubGuardFailure(masm);
+
+    return true;
+}
+
+bool
+ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
+{
+    Label failure;
+    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
+
+    switch (op) {
+      case JSOP_BITNOT:
+        masm.Mvn(ARMRegister(R1.valueReg(), 32), ARMRegister(R0.valueReg(), 32));
+        masm.movePayload(R1.valueReg(), R0.valueReg());
+        break;
+      case JSOP_NEG:
+        // Guard against 0 and MIN_INT, both result in a double.
+        masm.branchTest32(Assembler::Zero, R0.valueReg(), Imm32(0x7fffffff), &failure);
+
+        // Compile -x as 0 - x.
+        masm.Sub(ARMRegister(R1.valueReg(), 32), wzr, ARMRegister(R0.valueReg(), 32));
+        masm.movePayload(R1.valueReg(), R0.valueReg());
+        break;
+      default:
+        MOZ_CRASH("Unexpected op");
+    }
+
+    EmitReturnFromIC(masm);
+
+    masm.bind(&failure);
+    EmitStubGuardFailure(masm);
+    return true;
+
+}
+
+} // namespace jit
+} // namespace js
--- a/js/src/jit/mips32/BaselineIC-mips32.cpp
+++ b/js/src/jit/mips32/BaselineIC-mips32.cpp
@@ -62,163 +62,10 @@ ICCompare_Double::Compiler::generateStub
     EmitReturnFromIC(masm);
 
     // Failure case - jump to next stub
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
     return true;
 }
 
-// ICBinaryArith_Int32
-
-bool
-ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
-{
-    // Guard that R0 is an integer and R1 is an integer.
-    Label failure;
-    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
-    masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
-
-    // Add R0 and R1. Don't need to explicitly unbox, just use R2's payloadReg.
-    Register scratchReg = R2.payloadReg();
-
-    // DIV and MOD need an extra non-volatile ValueOperand to hold R0.
-    AllocatableGeneralRegisterSet savedRegs(availableGeneralRegs(2));
-    savedRegs.set() = GeneralRegisterSet::Intersect(GeneralRegisterSet::NonVolatile(), savedRegs.set());
-
-    Label goodMul, divTest1, divTest2;
-    switch(op_) {
-      case JSOP_ADD:
-        // We know R0.typeReg() already contains the integer tag. No boxing
-        // required.
-        masm.ma_addTestOverflow(scratchReg, R0.payloadReg(), R1.payloadReg(), &failure);
-        masm.move32(scratchReg, R0.payloadReg());
-        break;
-      case JSOP_SUB:
-        masm.ma_subTestOverflow(scratchReg, R0.payloadReg(), R1.payloadReg(), &failure);
-        masm.move32(scratchReg, R0.payloadReg());
-        break;
-      case JSOP_MUL: {
-        masm.ma_mul_branch_overflow(scratchReg, R0.payloadReg(), R1.payloadReg(), &failure);
-
-        masm.ma_b(scratchReg, Imm32(0), &goodMul, Assembler::NotEqual, ShortJump);
-
-        // Result is -0 if operands have different signs.
-        masm.as_xor(t8, R0.payloadReg(), R1.payloadReg());
-        masm.ma_b(t8, Imm32(0), &failure, Assembler::LessThan, ShortJump);
-
-        masm.bind(&goodMul);
-        masm.move32(scratchReg, R0.payloadReg());
-        break;
-      }
-      case JSOP_DIV:
-      case JSOP_MOD: {
-        // Check for INT_MIN / -1, it results in a double.
-        masm.ma_b(R0.payloadReg(), Imm32(INT_MIN), &divTest1, Assembler::NotEqual, ShortJump);
-        masm.ma_b(R1.payloadReg(), Imm32(-1), &failure, Assembler::Equal, ShortJump);
-        masm.bind(&divTest1);
-
-        // Check for division by zero
-        masm.ma_b(R1.payloadReg(), Imm32(0), &failure, Assembler::Equal, ShortJump);
-
-        // Check for 0 / X with X < 0 (results in -0).
-        masm.ma_b(R0.payloadReg(), Imm32(0), &divTest2, Assembler::NotEqual, ShortJump);
-        masm.ma_b(R1.payloadReg(), Imm32(0), &failure, Assembler::LessThan, ShortJump);
-        masm.bind(&divTest2);
-
-        masm.as_div(R0.payloadReg(), R1.payloadReg());
-
-        if (op_ == JSOP_DIV) {
-            // Result is a double if the remainder != 0.
-            masm.as_mfhi(scratchReg);
-            masm.ma_b(scratchReg, Imm32(0), &failure, Assembler::NotEqual, ShortJump);
-            masm.as_mflo(scratchReg);
-            masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
-        } else {
-            Label done;
-            // If X % Y == 0 and X < 0, the result is -0.
-            masm.as_mfhi(scratchReg);
-            masm.ma_b(scratchReg, Imm32(0), &done, Assembler::NotEqual, ShortJump);
-            masm.ma_b(R0.payloadReg(), Imm32(0), &failure, Assembler::LessThan, ShortJump);
-            masm.bind(&done);
-            masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
-        }
-        break;
-      }
-      case JSOP_BITOR:
-        masm.ma_or(R0.payloadReg() , R0.payloadReg(), R1.payloadReg());
-        break;
-      case JSOP_BITXOR:
-        masm.ma_xor(R0.payloadReg() , R0.payloadReg(), R1.payloadReg());
-        break;
-      case JSOP_BITAND:
-        masm.ma_and(R0.payloadReg() , R0.payloadReg(), R1.payloadReg());
-        break;
-      case JSOP_LSH:
-        // MIPS will only use 5 lowest bits in R1 as shift offset.
-        masm.ma_sll(R0.payloadReg(), R0.payloadReg(), R1.payloadReg());
-        break;
-      case JSOP_RSH:
-        masm.ma_sra(R0.payloadReg(), R0.payloadReg(), R1.payloadReg());
-        break;
-      case JSOP_URSH:
-        masm.ma_srl(scratchReg, R0.payloadReg(), R1.payloadReg());
-        if (allowDouble_) {
-            Label toUint;
-            masm.ma_b(scratchReg, Imm32(0), &toUint, Assembler::LessThan, ShortJump);
-
-            // Move result and box for return.
-            masm.move32(scratchReg, R0.payloadReg());
-            EmitReturnFromIC(masm);
-
-            masm.bind(&toUint);
-            masm.convertUInt32ToDouble(scratchReg, FloatReg1);
-            masm.boxDouble(FloatReg1, R0);
-        } else {
-            masm.ma_b(scratchReg, Imm32(0), &failure, Assembler::LessThan, ShortJump);
-            // Move result for return.
-            masm.move32(scratchReg, R0.payloadReg());
-        }
-        break;
-      default:
-        MOZ_CRASH("Unhandled op for BinaryArith_Int32.");
-    }
-
-    EmitReturnFromIC(masm);
-
-    // Failure case - jump to next stub
-    masm.bind(&failure);
-    EmitStubGuardFailure(masm);
-
-    return true;
-}
-
-bool
-ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
-{
-    Label failure;
-    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
-
-    switch (op) {
-      case JSOP_BITNOT:
-        masm.not32(R0.payloadReg());
-        break;
-      case JSOP_NEG:
-        // Guard against 0 and MIN_INT, both result in a double.
-        masm.branchTest32(Assembler::Zero, R0.payloadReg(), Imm32(INT32_MAX), &failure);
-
-        masm.neg32(R0.payloadReg());
-        break;
-      default:
-        MOZ_CRASH("Unexpected op");
-        return false;
-    }
-
-    EmitReturnFromIC(masm);
-
-    masm.bind(&failure);
-    EmitStubGuardFailure(masm);
-    return true;
-}
-
-
 } // namespace jit
 } // namespace js
new file mode 100644
--- /dev/null
+++ b/js/src/jit/mips32/SharedIC-mips32.cpp
@@ -0,0 +1,177 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * 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 "jsiter.h"
+
+#include "jit/BaselineCompiler.h"
+#include "jit/BaselineIC.h"
+#include "jit/BaselineJIT.h"
+#include "jit/Linker.h"
+#include "jit/SharedICHelpers.h"
+
+#include "jsboolinlines.h"
+
+using namespace js;
+using namespace js::jit;
+
+namespace js {
+namespace jit {
+
+// ICBinaryArith_Int32
+
+bool
+ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
+{
+    // Guard that R0 is an integer and R1 is an integer.
+    Label failure;
+    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
+    masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
+
+    // Add R0 and R1. Don't need to explicitly unbox, just use R2's payloadReg.
+    Register scratchReg = R2.payloadReg();
+
+    // DIV and MOD need an extra non-volatile ValueOperand to hold R0.
+    AllocatableGeneralRegisterSet savedRegs(availableGeneralRegs(2));
+    savedRegs.set() = GeneralRegisterSet::Intersect(GeneralRegisterSet::NonVolatile(), savedRegs.set());
+
+    Label goodMul, divTest1, divTest2;
+    switch(op_) {
+      case JSOP_ADD:
+        // We know R0.typeReg() already contains the integer tag. No boxing
+        // required.
+        masm.ma_addTestOverflow(scratchReg, R0.payloadReg(), R1.payloadReg(), &failure);
+        masm.move32(scratchReg, R0.payloadReg());
+        break;
+      case JSOP_SUB:
+        masm.ma_subTestOverflow(scratchReg, R0.payloadReg(), R1.payloadReg(), &failure);
+        masm.move32(scratchReg, R0.payloadReg());
+        break;
+      case JSOP_MUL: {
+        masm.ma_mul_branch_overflow(scratchReg, R0.payloadReg(), R1.payloadReg(), &failure);
+
+        masm.ma_b(scratchReg, Imm32(0), &goodMul, Assembler::NotEqual, ShortJump);
+
+        // Result is -0 if operands have different signs.
+        masm.as_xor(t8, R0.payloadReg(), R1.payloadReg());
+        masm.ma_b(t8, Imm32(0), &failure, Assembler::LessThan, ShortJump);
+
+        masm.bind(&goodMul);
+        masm.move32(scratchReg, R0.payloadReg());
+        break;
+      }
+      case JSOP_DIV:
+      case JSOP_MOD: {
+        // Check for INT_MIN / -1, it results in a double.
+        masm.ma_b(R0.payloadReg(), Imm32(INT_MIN), &divTest1, Assembler::NotEqual, ShortJump);
+        masm.ma_b(R1.payloadReg(), Imm32(-1), &failure, Assembler::Equal, ShortJump);
+        masm.bind(&divTest1);
+
+        // Check for division by zero
+        masm.ma_b(R1.payloadReg(), Imm32(0), &failure, Assembler::Equal, ShortJump);
+
+        // Check for 0 / X with X < 0 (results in -0).
+        masm.ma_b(R0.payloadReg(), Imm32(0), &divTest2, Assembler::NotEqual, ShortJump);
+        masm.ma_b(R1.payloadReg(), Imm32(0), &failure, Assembler::LessThan, ShortJump);
+        masm.bind(&divTest2);
+
+        masm.as_div(R0.payloadReg(), R1.payloadReg());
+
+        if (op_ == JSOP_DIV) {
+            // Result is a double if the remainder != 0.
+            masm.as_mfhi(scratchReg);
+            masm.ma_b(scratchReg, Imm32(0), &failure, Assembler::NotEqual, ShortJump);
+            masm.as_mflo(scratchReg);
+            masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
+        } else {
+            Label done;
+            // If X % Y == 0 and X < 0, the result is -0.
+            masm.as_mfhi(scratchReg);
+            masm.ma_b(scratchReg, Imm32(0), &done, Assembler::NotEqual, ShortJump);
+            masm.ma_b(R0.payloadReg(), Imm32(0), &failure, Assembler::LessThan, ShortJump);
+            masm.bind(&done);
+            masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
+        }
+        break;
+      }
+      case JSOP_BITOR:
+        masm.ma_or(R0.payloadReg() , R0.payloadReg(), R1.payloadReg());
+        break;
+      case JSOP_BITXOR:
+        masm.ma_xor(R0.payloadReg() , R0.payloadReg(), R1.payloadReg());
+        break;
+      case JSOP_BITAND:
+        masm.ma_and(R0.payloadReg() , R0.payloadReg(), R1.payloadReg());
+        break;
+      case JSOP_LSH:
+        // MIPS will only use 5 lowest bits in R1 as shift offset.
+        masm.ma_sll(R0.payloadReg(), R0.payloadReg(), R1.payloadReg());
+        break;
+      case JSOP_RSH:
+        masm.ma_sra(R0.payloadReg(), R0.payloadReg(), R1.payloadReg());
+        break;
+      case JSOP_URSH:
+        masm.ma_srl(scratchReg, R0.payloadReg(), R1.payloadReg());
+        if (allowDouble_) {
+            Label toUint;
+            masm.ma_b(scratchReg, Imm32(0), &toUint, Assembler::LessThan, ShortJump);
+
+            // Move result and box for return.
+            masm.move32(scratchReg, R0.payloadReg());
+            EmitReturnFromIC(masm);
+
+            masm.bind(&toUint);
+            masm.convertUInt32ToDouble(scratchReg, FloatReg1);
+            masm.boxDouble(FloatReg1, R0);
+        } else {
+            masm.ma_b(scratchReg, Imm32(0), &failure, Assembler::LessThan, ShortJump);
+            // Move result for return.
+            masm.move32(scratchReg, R0.payloadReg());
+        }
+        break;
+      default:
+        MOZ_CRASH("Unhandled op for BinaryArith_Int32.");
+    }
+
+    EmitReturnFromIC(masm);
+
+    // Failure case - jump to next stub
+    masm.bind(&failure);
+    EmitStubGuardFailure(masm);
+
+    return true;
+}
+
+bool
+ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
+{
+    Label failure;
+    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
+
+    switch (op) {
+      case JSOP_BITNOT:
+        masm.not32(R0.payloadReg());
+        break;
+      case JSOP_NEG:
+        // Guard against 0 and MIN_INT, both result in a double.
+        masm.branchTest32(Assembler::Zero, R0.payloadReg(), Imm32(INT32_MAX), &failure);
+
+        masm.neg32(R0.payloadReg());
+        break;
+      default:
+        MOZ_CRASH("Unexpected op");
+        return false;
+    }
+
+    EmitReturnFromIC(masm);
+
+    masm.bind(&failure);
+    EmitStubGuardFailure(masm);
+    return true;
+}
+
+
+} // namespace jit
+} // namespace js
--- a/js/src/jit/x64/BaselineIC-x64.cpp
+++ b/js/src/jit/x64/BaselineIC-x64.cpp
@@ -36,225 +36,10 @@ ICCompare_Int32::Compiler::generateStubC
 
     // Failure case - jump to next stub
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
 
     return true;
 }
 
-// ICBinaryArith_Int32
-
-bool
-ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
-{
-    // Guard that R0 is an integer and R1 is an integer.
-    Label failure;
-    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
-    masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
-
-    // The scratch register is only used in the case of JSOP_URSH.
-    mozilla::Maybe<ScratchRegisterScope> scratch;
-
-    Label revertRegister, maybeNegZero;
-    switch(op_) {
-      case JSOP_ADD:
-        masm.unboxInt32(R0, ExtractTemp0);
-        // Just jump to failure on overflow. R0 and R1 are preserved, so we can just jump to
-        // the next stub.
-        masm.addl(R1.valueReg(), ExtractTemp0);
-        masm.j(Assembler::Overflow, &failure);
-
-        // Box the result
-        masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
-        break;
-      case JSOP_SUB:
-        masm.unboxInt32(R0, ExtractTemp0);
-        masm.subl(R1.valueReg(), ExtractTemp0);
-        masm.j(Assembler::Overflow, &failure);
-        masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
-        break;
-      case JSOP_MUL:
-        masm.unboxInt32(R0, ExtractTemp0);
-        masm.imull(R1.valueReg(), ExtractTemp0);
-        masm.j(Assembler::Overflow, &failure);
-
-        masm.branchTest32(Assembler::Zero, ExtractTemp0, ExtractTemp0, &maybeNegZero);
-
-        masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
-        break;
-      case JSOP_DIV:
-      {
-        MOZ_ASSERT(R2.scratchReg() == rax);
-        MOZ_ASSERT(R0.valueReg() != rdx);
-        MOZ_ASSERT(R1.valueReg() != rdx);
-        masm.unboxInt32(R0, eax);
-        masm.unboxInt32(R1, ExtractTemp0);
-
-        // Prevent division by 0.
-        masm.branchTest32(Assembler::Zero, ExtractTemp0, ExtractTemp0, &failure);
-
-        // Prevent negative 0 and -2147483648 / -1.
-        masm.branch32(Assembler::Equal, eax, Imm32(INT32_MIN), &failure);
-
-        Label notZero;
-        masm.branch32(Assembler::NotEqual, eax, Imm32(0), &notZero);
-        masm.branchTest32(Assembler::Signed, ExtractTemp0, ExtractTemp0, &failure);
-        masm.bind(&notZero);
-
-        // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
-        masm.cdq();
-        masm.idiv(ExtractTemp0);
-
-        // A remainder implies a double result.
-        masm.branchTest32(Assembler::NonZero, edx, edx, &failure);
-
-        masm.boxValue(JSVAL_TYPE_INT32, eax, R0.valueReg());
-        break;
-      }
-      case JSOP_MOD:
-      {
-        MOZ_ASSERT(R2.scratchReg() == rax);
-        MOZ_ASSERT(R0.valueReg() != rdx);
-        MOZ_ASSERT(R1.valueReg() != rdx);
-        masm.unboxInt32(R0, eax);
-        masm.unboxInt32(R1, ExtractTemp0);
-
-        // x % 0 always results in NaN.
-        masm.branchTest32(Assembler::Zero, ExtractTemp0, ExtractTemp0, &failure);
-
-        // Prevent negative 0 and -2147483648 % -1.
-        masm.branchTest32(Assembler::Zero, eax, Imm32(0x7fffffff), &failure);
-
-        // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
-        masm.cdq();
-        masm.idiv(ExtractTemp0);
-
-        // Fail when we would need a negative remainder.
-        Label done;
-        masm.branchTest32(Assembler::NonZero, edx, edx, &done);
-        masm.orl(ExtractTemp0, eax);
-        masm.branchTest32(Assembler::Signed, eax, eax, &failure);
-
-        masm.bind(&done);
-        masm.boxValue(JSVAL_TYPE_INT32, edx, R0.valueReg());
-        break;
-      }
-      case JSOP_BITOR:
-        // We can overide R0, because the instruction is unfailable.
-        // Because the tag bits are the same, we don't need to retag.
-        masm.orq(R1.valueReg(), R0.valueReg());
-        break;
-      case JSOP_BITXOR:
-        masm.xorl(R1.valueReg(), R0.valueReg());
-        masm.tagValue(JSVAL_TYPE_INT32, R0.valueReg(), R0);
-        break;
-      case JSOP_BITAND:
-        masm.andq(R1.valueReg(), R0.valueReg());
-        break;
-      case JSOP_LSH:
-        masm.unboxInt32(R0, ExtractTemp0);
-        masm.unboxInt32(R1, ecx); // Unboxing R1 to ecx, clobbers R0.
-        masm.shll_cl(ExtractTemp0);
-        masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
-        break;
-      case JSOP_RSH:
-        masm.unboxInt32(R0, ExtractTemp0);
-        masm.unboxInt32(R1, ecx);
-        masm.sarl_cl(ExtractTemp0);
-        masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
-        break;
-      case JSOP_URSH:
-        if (!allowDouble_) {
-            scratch.emplace(masm);
-            masm.movq(R0.valueReg(), *scratch);
-        }
-
-        masm.unboxInt32(R0, ExtractTemp0);
-        masm.unboxInt32(R1, ecx); // This clobbers R0
-
-        masm.shrl_cl(ExtractTemp0);
-        masm.test32(ExtractTemp0, ExtractTemp0);
-        if (allowDouble_) {
-            Label toUint;
-            masm.j(Assembler::Signed, &toUint);
-
-            // Box and return.
-            masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
-            EmitReturnFromIC(masm);
-
-            masm.bind(&toUint);
-            ScratchDoubleScope scratchDouble(masm);
-            masm.convertUInt32ToDouble(ExtractTemp0, scratchDouble);
-            masm.boxDouble(scratchDouble, R0);
-        } else {
-            masm.j(Assembler::Signed, &revertRegister);
-            masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
-        }
-        break;
-      default:
-        MOZ_CRASH("Unhandled op in BinaryArith_Int32");
-    }
-
-    // Return from stub.
-    EmitReturnFromIC(masm);
-
-    if (op_ == JSOP_MUL) {
-        masm.bind(&maybeNegZero);
-
-        // Result is -0 if exactly one of lhs or rhs is negative.
-        {
-            ScratchRegisterScope scratch(masm);
-            masm.movl(R0.valueReg(), scratch);
-            masm.orl(R1.valueReg(), scratch);
-            masm.j(Assembler::Signed, &failure);
-        }
-
-        // Result is +0.
-        masm.moveValue(Int32Value(0), R0);
-        EmitReturnFromIC(masm);
-    }
-
-    // Revert the content of R0 in the fallible >>> case.
-    if (op_ == JSOP_URSH && !allowDouble_) {
-        // Scope continuation from JSOP_URSH case above.
-        masm.bind(&revertRegister);
-        // Restore tag and payload.
-        masm.movq(*scratch, R0.valueReg());
-        // Fall through to failure.
-    }
-    // Failure case - jump to next stub
-    masm.bind(&failure);
-    EmitStubGuardFailure(masm);
-
-    return true;
-}
-
-bool
-ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
-{
-    Label failure;
-    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
-
-    switch (op) {
-      case JSOP_BITNOT:
-        masm.notl(R0.valueReg());
-        break;
-      case JSOP_NEG:
-        // Guard against 0 and MIN_INT, both result in a double.
-        masm.branchTest32(Assembler::Zero, R0.valueReg(), Imm32(0x7fffffff), &failure);
-        masm.negl(R0.valueReg());
-        break;
-      default:
-        MOZ_CRASH("Unexpected op");
-    }
-
-    masm.tagValue(JSVAL_TYPE_INT32, R0.valueReg(), R0);
-
-    EmitReturnFromIC(masm);
-
-    masm.bind(&failure);
-    EmitStubGuardFailure(masm);
-    return true;
-}
-
 } // namespace jit
 } // namespace js
new file mode 100644
--- /dev/null
+++ b/js/src/jit/x64/SharedIC-x64.cpp
@@ -0,0 +1,232 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * 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 "jit/BaselineIC.h"
+#include "jit/SharedICHelpers.h"
+
+using namespace js;
+using namespace js::jit;
+
+namespace js {
+namespace jit {
+
+// ICBinaryArith_Int32
+
+bool
+ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
+{
+    // Guard that R0 is an integer and R1 is an integer.
+    Label failure;
+    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
+    masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
+
+    // The scratch register is only used in the case of JSOP_URSH.
+    mozilla::Maybe<ScratchRegisterScope> scratch;
+
+    Label revertRegister, maybeNegZero;
+    switch(op_) {
+      case JSOP_ADD:
+        masm.unboxInt32(R0, ExtractTemp0);
+        // Just jump to failure on overflow. R0 and R1 are preserved, so we can just jump to
+        // the next stub.
+        masm.addl(R1.valueReg(), ExtractTemp0);
+        masm.j(Assembler::Overflow, &failure);
+
+        // Box the result
+        masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
+        break;
+      case JSOP_SUB:
+        masm.unboxInt32(R0, ExtractTemp0);
+        masm.subl(R1.valueReg(), ExtractTemp0);
+        masm.j(Assembler::Overflow, &failure);
+        masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
+        break;
+      case JSOP_MUL:
+        masm.unboxInt32(R0, ExtractTemp0);
+        masm.imull(R1.valueReg(), ExtractTemp0);
+        masm.j(Assembler::Overflow, &failure);
+
+        masm.branchTest32(Assembler::Zero, ExtractTemp0, ExtractTemp0, &maybeNegZero);
+
+        masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
+        break;
+      case JSOP_DIV:
+      {
+        MOZ_ASSERT(R2.scratchReg() == rax);
+        MOZ_ASSERT(R0.valueReg() != rdx);
+        MOZ_ASSERT(R1.valueReg() != rdx);
+        masm.unboxInt32(R0, eax);
+        masm.unboxInt32(R1, ExtractTemp0);
+
+        // Prevent division by 0.
+        masm.branchTest32(Assembler::Zero, ExtractTemp0, ExtractTemp0, &failure);
+
+        // Prevent negative 0 and -2147483648 / -1.
+        masm.branch32(Assembler::Equal, eax, Imm32(INT32_MIN), &failure);
+
+        Label notZero;
+        masm.branch32(Assembler::NotEqual, eax, Imm32(0), &notZero);
+        masm.branchTest32(Assembler::Signed, ExtractTemp0, ExtractTemp0, &failure);
+        masm.bind(&notZero);
+
+        // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
+        masm.cdq();
+        masm.idiv(ExtractTemp0);
+
+        // A remainder implies a double result.
+        masm.branchTest32(Assembler::NonZero, edx, edx, &failure);
+
+        masm.boxValue(JSVAL_TYPE_INT32, eax, R0.valueReg());
+        break;
+      }
+      case JSOP_MOD:
+      {
+        MOZ_ASSERT(R2.scratchReg() == rax);
+        MOZ_ASSERT(R0.valueReg() != rdx);
+        MOZ_ASSERT(R1.valueReg() != rdx);
+        masm.unboxInt32(R0, eax);
+        masm.unboxInt32(R1, ExtractTemp0);
+
+        // x % 0 always results in NaN.
+        masm.branchTest32(Assembler::Zero, ExtractTemp0, ExtractTemp0, &failure);
+
+        // Prevent negative 0 and -2147483648 % -1.
+        masm.branchTest32(Assembler::Zero, eax, Imm32(0x7fffffff), &failure);
+
+        // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
+        masm.cdq();
+        masm.idiv(ExtractTemp0);
+
+        // Fail when we would need a negative remainder.
+        Label done;
+        masm.branchTest32(Assembler::NonZero, edx, edx, &done);
+        masm.orl(ExtractTemp0, eax);
+        masm.branchTest32(Assembler::Signed, eax, eax, &failure);
+
+        masm.bind(&done);
+        masm.boxValue(JSVAL_TYPE_INT32, edx, R0.valueReg());
+        break;
+      }
+      case JSOP_BITOR:
+        // We can overide R0, because the instruction is unfailable.
+        // Because the tag bits are the same, we don't need to retag.
+        masm.orq(R1.valueReg(), R0.valueReg());
+        break;
+      case JSOP_BITXOR:
+        masm.xorl(R1.valueReg(), R0.valueReg());
+        masm.tagValue(JSVAL_TYPE_INT32, R0.valueReg(), R0);
+        break;
+      case JSOP_BITAND:
+        masm.andq(R1.valueReg(), R0.valueReg());
+        break;
+      case JSOP_LSH:
+        masm.unboxInt32(R0, ExtractTemp0);
+        masm.unboxInt32(R1, ecx); // Unboxing R1 to ecx, clobbers R0.
+        masm.shll_cl(ExtractTemp0);
+        masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
+        break;
+      case JSOP_RSH:
+        masm.unboxInt32(R0, ExtractTemp0);
+        masm.unboxInt32(R1, ecx);
+        masm.sarl_cl(ExtractTemp0);
+        masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
+        break;
+      case JSOP_URSH:
+        if (!allowDouble_) {
+            scratch.emplace(masm);
+            masm.movq(R0.valueReg(), *scratch);
+        }
+
+        masm.unboxInt32(R0, ExtractTemp0);
+        masm.unboxInt32(R1, ecx); // This clobbers R0
+
+        masm.shrl_cl(ExtractTemp0);
+        masm.test32(ExtractTemp0, ExtractTemp0);
+        if (allowDouble_) {
+            Label toUint;
+            masm.j(Assembler::Signed, &toUint);
+
+            // Box and return.
+            masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
+            EmitReturnFromIC(masm);
+
+            masm.bind(&toUint);
+            ScratchDoubleScope scratchDouble(masm);
+            masm.convertUInt32ToDouble(ExtractTemp0, scratchDouble);
+            masm.boxDouble(scratchDouble, R0);
+        } else {
+            masm.j(Assembler::Signed, &revertRegister);
+            masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
+        }
+        break;
+      default:
+        MOZ_CRASH("Unhandled op in BinaryArith_Int32");
+    }
+
+    // Return from stub.
+    EmitReturnFromIC(masm);
+
+    if (op_ == JSOP_MUL) {
+        masm.bind(&maybeNegZero);
+
+        // Result is -0 if exactly one of lhs or rhs is negative.
+        {
+            ScratchRegisterScope scratch(masm);
+            masm.movl(R0.valueReg(), scratch);
+            masm.orl(R1.valueReg(), scratch);
+            masm.j(Assembler::Signed, &failure);
+        }
+
+        // Result is +0.
+        masm.moveValue(Int32Value(0), R0);
+        EmitReturnFromIC(masm);
+    }
+
+    // Revert the content of R0 in the fallible >>> case.
+    if (op_ == JSOP_URSH && !allowDouble_) {
+        // Scope continuation from JSOP_URSH case above.
+        masm.bind(&revertRegister);
+        // Restore tag and payload.
+        masm.movq(*scratch, R0.valueReg());
+        // Fall through to failure.
+    }
+    // Failure case - jump to next stub
+    masm.bind(&failure);
+    EmitStubGuardFailure(masm);
+
+    return true;
+}
+
+bool
+ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
+{
+    Label failure;
+    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
+
+    switch (op) {
+      case JSOP_BITNOT:
+        masm.notl(R0.valueReg());
+        break;
+      case JSOP_NEG:
+        // Guard against 0 and MIN_INT, both result in a double.
+        masm.branchTest32(Assembler::Zero, R0.valueReg(), Imm32(0x7fffffff), &failure);
+        masm.negl(R0.valueReg());
+        break;
+      default:
+        MOZ_CRASH("Unexpected op");
+    }
+
+    masm.tagValue(JSVAL_TYPE_INT32, R0.valueReg(), R0);
+
+    EmitReturnFromIC(masm);
+
+    masm.bind(&failure);
+    EmitStubGuardFailure(masm);
+    return true;
+}
+
+} // namespace jit
+} // namespace js
--- a/js/src/jit/x86/BaselineIC-x86.cpp
+++ b/js/src/jit/x86/BaselineIC-x86.cpp
@@ -37,230 +37,10 @@ ICCompare_Int32::Compiler::generateStubC
     EmitReturnFromIC(masm);
 
     // Failure case - jump to next stub
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
     return true;
 }
 
-// ICBinaryArith_Int32
-
-bool
-ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
-{
-    // Guard that R0 is an integer and R1 is an integer.
-    Label failure;
-    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
-    masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
-
-    // Add R0 and R1.  Don't need to explicitly unbox, just use the TailCallReg which
-    // should be available.
-    Register scratchReg = ICTailCallReg;
-
-    Label revertRegister, maybeNegZero;
-    switch(op_) {
-      case JSOP_ADD:
-        // Add R0 and R1.  Don't need to explicitly unbox.
-        masm.movl(R0.payloadReg(), scratchReg);
-        masm.addl(R1.payloadReg(), scratchReg);
-
-        // Just jump to failure on overflow.  R0 and R1 are preserved, so we can just jump to
-        // the next stub.
-        masm.j(Assembler::Overflow, &failure);
-
-        // Just overwrite the payload, the tag is still fine.
-        masm.movl(scratchReg, R0.payloadReg());
-        break;
-      case JSOP_SUB:
-        masm.movl(R0.payloadReg(), scratchReg);
-        masm.subl(R1.payloadReg(), scratchReg);
-        masm.j(Assembler::Overflow, &failure);
-        masm.movl(scratchReg, R0.payloadReg());
-        break;
-      case JSOP_MUL:
-        masm.movl(R0.payloadReg(), scratchReg);
-        masm.imull(R1.payloadReg(), scratchReg);
-        masm.j(Assembler::Overflow, &failure);
-
-        masm.test32(scratchReg, scratchReg);
-        masm.j(Assembler::Zero, &maybeNegZero);
-
-        masm.movl(scratchReg, R0.payloadReg());
-        break;
-      case JSOP_DIV:
-      {
-        // Prevent division by 0.
-        masm.branchTest32(Assembler::Zero, R1.payloadReg(), R1.payloadReg(), &failure);
-
-        // Prevent negative 0 and -2147483648 / -1.
-        masm.branch32(Assembler::Equal, R0.payloadReg(), Imm32(INT32_MIN), &failure);
-
-        Label notZero;
-        masm.branch32(Assembler::NotEqual, R0.payloadReg(), Imm32(0), &notZero);
-        masm.branchTest32(Assembler::Signed, R1.payloadReg(), R1.payloadReg(), &failure);
-        masm.bind(&notZero);
-
-        // For idiv we need eax.
-        MOZ_ASSERT(R1.typeReg() == eax);
-        masm.movl(R0.payloadReg(), eax);
-        // Preserve R0.payloadReg()/edx, eax is JSVAL_TYPE_INT32.
-        masm.movl(R0.payloadReg(), scratchReg);
-        // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
-        masm.cdq();
-        masm.idiv(R1.payloadReg());
-
-        // A remainder implies a double result.
-        masm.branchTest32(Assembler::NonZero, edx, edx, &revertRegister);
-
-        masm.movl(eax, R0.payloadReg());
-        break;
-      }
-      case JSOP_MOD:
-      {
-        // x % 0 always results in NaN.
-        masm.branchTest32(Assembler::Zero, R1.payloadReg(), R1.payloadReg(), &failure);
-
-        // Prevent negative 0 and -2147483648 % -1.
-        masm.branchTest32(Assembler::Zero, R0.payloadReg(), Imm32(0x7fffffff), &failure);
-
-        // For idiv we need eax.
-        MOZ_ASSERT(R1.typeReg() == eax);
-        masm.movl(R0.payloadReg(), eax);
-        // Preserve R0.payloadReg()/edx, eax is JSVAL_TYPE_INT32.
-        masm.movl(R0.payloadReg(), scratchReg);
-        // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
-        masm.cdq();
-        masm.idiv(R1.payloadReg());
-
-        // Fail when we would need a negative remainder.
-        Label done;
-        masm.branchTest32(Assembler::NonZero, edx, edx, &done);
-        masm.branchTest32(Assembler::Signed, scratchReg, scratchReg, &revertRegister);
-        masm.branchTest32(Assembler::Signed, R1.payloadReg(), R1.payloadReg(), &revertRegister);
-
-        masm.bind(&done);
-        // Result is in edx, tag in ecx remains untouched.
-        MOZ_ASSERT(R0.payloadReg() == edx);
-        MOZ_ASSERT(R0.typeReg() == ecx);
-        break;
-      }
-      case JSOP_BITOR:
-        // We can overide R0, because the instruction is unfailable.
-        // The R0.typeReg() is also still intact.
-        masm.orl(R1.payloadReg(), R0.payloadReg());
-        break;
-      case JSOP_BITXOR:
-        masm.xorl(R1.payloadReg(), R0.payloadReg());
-        break;
-      case JSOP_BITAND:
-        masm.andl(R1.payloadReg(), R0.payloadReg());
-        break;
-      case JSOP_LSH:
-        // RHS needs to be in ecx for shift operations.
-        MOZ_ASSERT(R0.typeReg() == ecx);
-        masm.movl(R1.payloadReg(), ecx);
-        masm.shll_cl(R0.payloadReg());
-        // We need to tag again, because we overwrote it.
-        masm.tagValue(JSVAL_TYPE_INT32, R0.payloadReg(), R0);
-        break;
-      case JSOP_RSH:
-        masm.movl(R1.payloadReg(), ecx);
-        masm.sarl_cl(R0.payloadReg());
-        masm.tagValue(JSVAL_TYPE_INT32, R0.payloadReg(), R0);
-        break;
-      case JSOP_URSH:
-        if (!allowDouble_)
-            masm.movl(R0.payloadReg(), scratchReg);
-
-        masm.movl(R1.payloadReg(), ecx);
-        masm.shrl_cl(R0.payloadReg());
-        masm.test32(R0.payloadReg(), R0.payloadReg());
-        if (allowDouble_) {
-            Label toUint;
-            masm.j(Assembler::Signed, &toUint);
-
-            // Box and return.
-            masm.tagValue(JSVAL_TYPE_INT32, R0.payloadReg(), R0);
-            EmitReturnFromIC(masm);
-
-            masm.bind(&toUint);
-            masm.convertUInt32ToDouble(R0.payloadReg(), ScratchDoubleReg);
-            masm.boxDouble(ScratchDoubleReg, R0);
-        } else {
-            masm.j(Assembler::Signed, &revertRegister);
-            masm.tagValue(JSVAL_TYPE_INT32, R0.payloadReg(), R0);
-        }
-        break;
-      default:
-       MOZ_CRASH("Unhandled op for BinaryArith_Int32.");
-    }
-
-    // Return.
-    EmitReturnFromIC(masm);
-
-    switch(op_) {
-      case JSOP_MUL:
-        masm.bind(&maybeNegZero);
-
-        // Result is -0 if exactly one of lhs or rhs is negative.
-        masm.movl(R0.payloadReg(), scratchReg);
-        masm.orl(R1.payloadReg(), scratchReg);
-        masm.j(Assembler::Signed, &failure);
-
-        // Result is +0.
-        masm.mov(ImmWord(0), R0.payloadReg());
-        EmitReturnFromIC(masm);
-        break;
-      case JSOP_DIV:
-      case JSOP_MOD:
-        masm.bind(&revertRegister);
-        masm.movl(scratchReg, R0.payloadReg());
-        masm.movl(ImmType(JSVAL_TYPE_INT32), R1.typeReg());
-        break;
-      case JSOP_URSH:
-        // Revert the content of R0 in the fallible >>> case.
-        if (!allowDouble_) {
-            masm.bind(&revertRegister);
-            masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
-        }
-        break;
-      default:
-        // No special failure handling required.
-        // Fall through to failure.
-        break;
-    }
-
-    // Failure case - jump to next stub
-    masm.bind(&failure);
-    EmitStubGuardFailure(masm);
-
-    return true;
-}
-
-bool
-ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
-{
-    Label failure;
-    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
-
-    switch (op) {
-      case JSOP_BITNOT:
-        masm.notl(R0.payloadReg());
-        break;
-      case JSOP_NEG:
-        // Guard against 0 and MIN_INT, both result in a double.
-        masm.branchTest32(Assembler::Zero, R0.payloadReg(), Imm32(0x7fffffff), &failure);
-        masm.negl(R0.payloadReg());
-        break;
-      default:
-        MOZ_CRASH("Unexpected op");
-    }
-
-    EmitReturnFromIC(masm);
-
-    masm.bind(&failure);
-    EmitStubGuardFailure(masm);
-    return true;
-}
-
 } // namespace jit
 } // namespace js
new file mode 100644
--- /dev/null
+++ b/js/src/jit/x86/SharedIC-x86.cpp
@@ -0,0 +1,240 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * 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 "jit/BaselineCompiler.h"
+#include "jit/BaselineIC.h"
+#include "jit/BaselineJIT.h"
+#include "jit/Linker.h"
+#include "jit/SharedICHelpers.h"
+
+using namespace js;
+using namespace js::jit;
+
+namespace js {
+namespace jit {
+
+// ICBinaryArith_Int32
+
+bool
+ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
+{
+    // Guard that R0 is an integer and R1 is an integer.
+    Label failure;
+    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
+    masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
+
+    // Add R0 and R1.  Don't need to explicitly unbox, just use the TailCallReg which
+    // should be available.
+    Register scratchReg = ICTailCallReg;
+
+    Label revertRegister, maybeNegZero;
+    switch(op_) {
+      case JSOP_ADD:
+        // Add R0 and R1.  Don't need to explicitly unbox.
+        masm.movl(R0.payloadReg(), scratchReg);
+        masm.addl(R1.payloadReg(), scratchReg);
+
+        // Just jump to failure on overflow.  R0 and R1 are preserved, so we can just jump to
+        // the next stub.
+        masm.j(Assembler::Overflow, &failure);
+
+        // Just overwrite the payload, the tag is still fine.
+        masm.movl(scratchReg, R0.payloadReg());
+        break;
+      case JSOP_SUB:
+        masm.movl(R0.payloadReg(), scratchReg);
+        masm.subl(R1.payloadReg(), scratchReg);
+        masm.j(Assembler::Overflow, &failure);
+        masm.movl(scratchReg, R0.payloadReg());
+        break;
+      case JSOP_MUL:
+        masm.movl(R0.payloadReg(), scratchReg);
+        masm.imull(R1.payloadReg(), scratchReg);
+        masm.j(Assembler::Overflow, &failure);
+
+        masm.test32(scratchReg, scratchReg);
+        masm.j(Assembler::Zero, &maybeNegZero);
+
+        masm.movl(scratchReg, R0.payloadReg());
+        break;
+      case JSOP_DIV:
+      {
+        // Prevent division by 0.
+        masm.branchTest32(Assembler::Zero, R1.payloadReg(), R1.payloadReg(), &failure);
+
+        // Prevent negative 0 and -2147483648 / -1.
+        masm.branch32(Assembler::Equal, R0.payloadReg(), Imm32(INT32_MIN), &failure);
+
+        Label notZero;
+        masm.branch32(Assembler::NotEqual, R0.payloadReg(), Imm32(0), &notZero);
+        masm.branchTest32(Assembler::Signed, R1.payloadReg(), R1.payloadReg(), &failure);
+        masm.bind(&notZero);
+
+        // For idiv we need eax.
+        MOZ_ASSERT(R1.typeReg() == eax);
+        masm.movl(R0.payloadReg(), eax);
+        // Preserve R0.payloadReg()/edx, eax is JSVAL_TYPE_INT32.
+        masm.movl(R0.payloadReg(), scratchReg);
+        // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
+        masm.cdq();
+        masm.idiv(R1.payloadReg());
+
+        // A remainder implies a double result.
+        masm.branchTest32(Assembler::NonZero, edx, edx, &revertRegister);
+
+        masm.movl(eax, R0.payloadReg());
+        break;
+      }
+      case JSOP_MOD:
+      {
+        // x % 0 always results in NaN.
+        masm.branchTest32(Assembler::Zero, R1.payloadReg(), R1.payloadReg(), &failure);
+
+        // Prevent negative 0 and -2147483648 % -1.
+        masm.branchTest32(Assembler::Zero, R0.payloadReg(), Imm32(0x7fffffff), &failure);
+
+        // For idiv we need eax.
+        MOZ_ASSERT(R1.typeReg() == eax);
+        masm.movl(R0.payloadReg(), eax);
+        // Preserve R0.payloadReg()/edx, eax is JSVAL_TYPE_INT32.
+        masm.movl(R0.payloadReg(), scratchReg);
+        // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
+        masm.cdq();
+        masm.idiv(R1.payloadReg());
+
+        // Fail when we would need a negative remainder.
+        Label done;
+        masm.branchTest32(Assembler::NonZero, edx, edx, &done);
+        masm.branchTest32(Assembler::Signed, scratchReg, scratchReg, &revertRegister);
+        masm.branchTest32(Assembler::Signed, R1.payloadReg(), R1.payloadReg(), &revertRegister);
+
+        masm.bind(&done);
+        // Result is in edx, tag in ecx remains untouched.
+        MOZ_ASSERT(R0.payloadReg() == edx);
+        MOZ_ASSERT(R0.typeReg() == ecx);
+        break;
+      }
+      case JSOP_BITOR:
+        // We can overide R0, because the instruction is unfailable.
+        // The R0.typeReg() is also still intact.
+        masm.orl(R1.payloadReg(), R0.payloadReg());
+        break;
+      case JSOP_BITXOR:
+        masm.xorl(R1.payloadReg(), R0.payloadReg());
+        break;
+      case JSOP_BITAND:
+        masm.andl(R1.payloadReg(), R0.payloadReg());
+        break;
+      case JSOP_LSH:
+        // RHS needs to be in ecx for shift operations.
+        MOZ_ASSERT(R0.typeReg() == ecx);
+        masm.movl(R1.payloadReg(), ecx);
+        masm.shll_cl(R0.payloadReg());
+        // We need to tag again, because we overwrote it.
+        masm.tagValue(JSVAL_TYPE_INT32, R0.payloadReg(), R0);
+        break;
+      case JSOP_RSH:
+        masm.movl(R1.payloadReg(), ecx);
+        masm.sarl_cl(R0.payloadReg());
+        masm.tagValue(JSVAL_TYPE_INT32, R0.payloadReg(), R0);
+        break;
+      case JSOP_URSH:
+        if (!allowDouble_)
+            masm.movl(R0.payloadReg(), scratchReg);
+
+        masm.movl(R1.payloadReg(), ecx);
+        masm.shrl_cl(R0.payloadReg());
+        masm.test32(R0.payloadReg(), R0.payloadReg());
+        if (allowDouble_) {
+            Label toUint;
+            masm.j(Assembler::Signed, &toUint);
+
+            // Box and return.
+            masm.tagValue(JSVAL_TYPE_INT32, R0.payloadReg(), R0);
+            EmitReturnFromIC(masm);
+
+            masm.bind(&toUint);
+            masm.convertUInt32ToDouble(R0.payloadReg(), ScratchDoubleReg);
+            masm.boxDouble(ScratchDoubleReg, R0);
+        } else {
+            masm.j(Assembler::Signed, &revertRegister);
+            masm.tagValue(JSVAL_TYPE_INT32, R0.payloadReg(), R0);
+        }
+        break;
+      default:
+       MOZ_CRASH("Unhandled op for BinaryArith_Int32.");
+    }
+
+    // Return.
+    EmitReturnFromIC(masm);
+
+    switch(op_) {
+      case JSOP_MUL:
+        masm.bind(&maybeNegZero);
+
+        // Result is -0 if exactly one of lhs or rhs is negative.
+        masm.movl(R0.payloadReg(), scratchReg);
+        masm.orl(R1.payloadReg(), scratchReg);
+        masm.j(Assembler::Signed, &failure);
+
+        // Result is +0.
+        masm.mov(ImmWord(0), R0.payloadReg());
+        EmitReturnFromIC(masm);
+        break;
+      case JSOP_DIV:
+      case JSOP_MOD:
+        masm.bind(&revertRegister);
+        masm.movl(scratchReg, R0.payloadReg());
+        masm.movl(ImmType(JSVAL_TYPE_INT32), R1.typeReg());
+        break;
+      case JSOP_URSH:
+        // Revert the content of R0 in the fallible >>> case.
+        if (!allowDouble_) {
+            masm.bind(&revertRegister);
+            masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
+        }
+        break;
+      default:
+        // No special failure handling required.
+        // Fall through to failure.
+        break;
+    }
+
+    // Failure case - jump to next stub
+    masm.bind(&failure);
+    EmitStubGuardFailure(masm);
+
+    return true;
+}
+
+bool
+ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
+{
+    Label failure;
+    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
+
+    switch (op) {
+      case JSOP_BITNOT:
+        masm.notl(R0.payloadReg());
+        break;
+      case JSOP_NEG:
+        // Guard against 0 and MIN_INT, both result in a double.
+        masm.branchTest32(Assembler::Zero, R0.payloadReg(), Imm32(0x7fffffff), &failure);
+        masm.negl(R0.payloadReg());
+        break;
+      default:
+        MOZ_CRASH("Unexpected op");
+    }
+
+    EmitReturnFromIC(masm);
+
+    masm.bind(&failure);
+    EmitStubGuardFailure(masm);
+    return true;
+}
+
+} // namespace jit
+} // namespace js
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -395,58 +395,62 @@ elif CONFIG['JS_CODEGEN_X86'] or CONFIG[
         UNIFIED_SOURCES += [
             'jit/x64/Assembler-x64.cpp',
             'jit/x64/Bailouts-x64.cpp',
             'jit/x64/BaselineCompiler-x64.cpp',
             'jit/x64/BaselineIC-x64.cpp',
             'jit/x64/CodeGenerator-x64.cpp',
             'jit/x64/Lowering-x64.cpp',
             'jit/x64/MacroAssembler-x64.cpp',
+            'jit/x64/SharedIC-x64.cpp',
             'jit/x64/Trampoline-x64.cpp',
         ]
     else:
         UNIFIED_SOURCES += [
             'jit/x86/Assembler-x86.cpp',
             'jit/x86/Bailouts-x86.cpp',
             'jit/x86/BaselineCompiler-x86.cpp',
             'jit/x86/BaselineIC-x86.cpp',
             'jit/x86/CodeGenerator-x86.cpp',
             'jit/x86/Lowering-x86.cpp',
             'jit/x86/MacroAssembler-x86.cpp',
+            'jit/x86/SharedIC-x86.cpp',
             'jit/x86/Trampoline-x86.cpp',
         ]
 elif CONFIG['JS_CODEGEN_ARM']:
     UNIFIED_SOURCES += [
         'jit/arm/Architecture-arm.cpp',
         'jit/arm/Assembler-arm.cpp',
         'jit/arm/Bailouts-arm.cpp',
         'jit/arm/BaselineCompiler-arm.cpp',
         'jit/arm/BaselineIC-arm.cpp',
         'jit/arm/CodeGenerator-arm.cpp',
         'jit/arm/disasm/Constants-arm.cpp',
         'jit/arm/disasm/Disasm-arm.cpp',
         'jit/arm/Lowering-arm.cpp',
         'jit/arm/MacroAssembler-arm.cpp',
         'jit/arm/MoveEmitter-arm.cpp',
+        'jit/arm/SharedIC-arm.cpp',
         'jit/arm/Trampoline-arm.cpp',
     ]
     if CONFIG['JS_SIMULATOR_ARM']:
         UNIFIED_SOURCES += [
             'jit/arm/Simulator-arm.cpp'
         ]
 elif CONFIG['JS_CODEGEN_ARM64']:
     UNIFIED_SOURCES += [
         'jit/arm64/Architecture-arm64.cpp',
         'jit/arm64/Assembler-arm64.cpp',
         'jit/arm64/Bailouts-arm64.cpp',
         'jit/arm64/BaselineIC-arm64.cpp',
         'jit/arm64/CodeGenerator-arm64.cpp',
         'jit/arm64/Lowering-arm64.cpp',
         'jit/arm64/MacroAssembler-arm64.cpp',
         'jit/arm64/MoveEmitter-arm64.cpp',
+        'jit/arm64/SharedIC-arm64.cpp',
         'jit/arm64/Trampoline-arm64.cpp',
         'jit/arm64/vixl/Assembler-vixl.cpp',
         'jit/arm64/vixl/Cpu-vixl.cpp',
         'jit/arm64/vixl/Decoder-vixl.cpp',
         'jit/arm64/vixl/Disasm-vixl.cpp',
         'jit/arm64/vixl/Instructions-vixl.cpp',
         'jit/arm64/vixl/Instrument-vixl.cpp',
         'jit/arm64/vixl/MacroAssembler-vixl.cpp',
@@ -470,16 +474,17 @@ elif CONFIG['JS_CODEGEN_MIPS32']:
             'jit/mips32/Assembler-mips32.cpp',
             'jit/mips32/Bailouts-mips32.cpp',
             'jit/mips32/BaselineCompiler-mips32.cpp',
             'jit/mips32/BaselineIC-mips32.cpp',
             'jit/mips32/CodeGenerator-mips32.cpp',
             'jit/mips32/Lowering-mips32.cpp',
             'jit/mips32/MacroAssembler-mips32.cpp',
             'jit/mips32/MoveEmitter-mips32.cpp',
+            'jit/mips32/SharedIC-mips32.cpp',
             'jit/mips32/Trampoline-mips32.cpp',
         ]
         if CONFIG['JS_SIMULATOR_MIPS32']:
             UNIFIED_SOURCES += [
                 'jit/mips32/Simulator-mips32.cpp'
             ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':