Bug 1077014 - MacroAssembler API. r=h4writer
authorLars T Hansen <lhansen@mozilla.com>
Tue, 17 Mar 2015 16:30:49 +0100
changeset 234117 01e1baebdd64de7592f09230cfb0b47c307a142e
parent 234116 1949f82ba1bad73d796f2920ece28fbbff88a727
child 234118 c741c522c1081b72da0f0913045d63693ef7a230
push id14540
push userkwierso@gmail.com
push dateWed, 18 Mar 2015 02:07:12 +0000
treeherderb2g-inbound@a9e16cd974b2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersh4writer
bugs1077014
milestone39.0a1
Bug 1077014 - MacroAssembler API. r=h4writer
js/src/jit/MacroAssembler.cpp
js/src/jit/MacroAssembler.h
js/src/jit/arm/MacroAssembler-arm.h
js/src/jit/none/MacroAssembler-none.h
js/src/jit/shared/MacroAssembler-x86-shared.h
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -637,16 +637,108 @@ template void
 MacroAssembler::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType,
                                            const Register &value, const Address &mem,
                                            Register temp1, Register temp2, AnyRegister output);
 template void
 MacroAssembler::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType,
                                            const Register &value, const BaseIndex &mem,
                                            Register temp1, Register temp2, AnyRegister output);
 
+// Binary operation for effect, result discarded.
+template<typename S, typename T>
+void
+MacroAssembler::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType, const S &value,
+                                           const T &mem)
+{
+    // Uint8Clamped is explicitly not supported here
+    switch (arrayType) {
+      case Scalar::Int8:
+      case Scalar::Uint8:
+        switch (op) {
+          case AtomicFetchAddOp:
+            atomicAdd8(value, mem);
+            break;
+          case AtomicFetchSubOp:
+            atomicSub8(value, mem);
+            break;
+          case AtomicFetchAndOp:
+            atomicAnd8(value, mem);
+            break;
+          case AtomicFetchOrOp:
+            atomicOr8(value, mem);
+            break;
+          case AtomicFetchXorOp:
+            atomicXor8(value, mem);
+            break;
+          default:
+            MOZ_CRASH("Invalid typed array atomic operation");
+        }
+        break;
+      case Scalar::Int16:
+      case Scalar::Uint16:
+        switch (op) {
+          case AtomicFetchAddOp:
+            atomicAdd16(value, mem);
+            break;
+          case AtomicFetchSubOp:
+            atomicSub16(value, mem);
+            break;
+          case AtomicFetchAndOp:
+            atomicAnd16(value, mem);
+            break;
+          case AtomicFetchOrOp:
+            atomicOr16(value, mem);
+            break;
+          case AtomicFetchXorOp:
+            atomicXor16(value, mem);
+            break;
+          default:
+            MOZ_CRASH("Invalid typed array atomic operation");
+        }
+        break;
+      case Scalar::Int32:
+      case Scalar::Uint32:
+        switch (op) {
+          case AtomicFetchAddOp:
+            atomicAdd32(value, mem);
+            break;
+          case AtomicFetchSubOp:
+            atomicSub32(value, mem);
+            break;
+          case AtomicFetchAndOp:
+            atomicAnd32(value, mem);
+            break;
+          case AtomicFetchOrOp:
+            atomicOr32(value, mem);
+            break;
+          case AtomicFetchXorOp:
+            atomicXor32(value, mem);
+            break;
+          default:
+            MOZ_CRASH("Invalid typed array atomic operation");
+        }
+        break;
+      default:
+        MOZ_CRASH("Invalid typed array type");
+    }
+}
+
+template void
+MacroAssembler::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType,
+                                           const Imm32 &value, const Address &mem);
+template void
+MacroAssembler::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType,
+                                           const Imm32 &value, const BaseIndex &mem);
+template void
+MacroAssembler::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType,
+                                           const Register &value, const Address &mem);
+template void
+MacroAssembler::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType,
+                                           const Register &value, const BaseIndex &mem);
+
 template <typename T>
 void
 MacroAssembler::loadUnboxedProperty(T address, JSValueType type, TypedOrValueRegister output)
 {
     switch (type) {
       case JSVAL_TYPE_BOOLEAN:
       case JSVAL_TYPE_INT32:
       case JSVAL_TYPE_STRING: {
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -743,20 +743,25 @@ class MacroAssembler : public MacroAssem
             MOZ_CRASH("Invalid typed array type");
         }
     }
 
     template<typename T>
     void compareExchangeToTypedIntArray(Scalar::Type arrayType, const T &mem, Register oldval, Register newval,
                                         Register temp, AnyRegister output);
 
+    // Generating a result.
     template<typename S, typename T>
     void atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType, const S &value,
                                     const T &mem, Register temp1, Register temp2, AnyRegister output);
 
+    // Generating no result.
+    template<typename S, typename T>
+    void atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType, const S &value, const T &mem);
+
     void storeToTypedFloatArray(Scalar::Type arrayType, FloatRegister value, const BaseIndex &dest);
     void storeToTypedFloatArray(Scalar::Type arrayType, FloatRegister value, const Address &dest);
 
     // Load a property from an UnboxedPlainObject.
     template <typename T>
     void loadUnboxedProperty(T address, JSValueType type, TypedOrValueRegister output);
 
     // Store a property to an UnboxedPlainObject, without triggering barriers.
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -1489,16 +1489,28 @@ class MacroAssemblerARMCompat : public M
     template<typename T>
     void atomicFetchOp(int nbytes, bool signExtend, AtomicOp op, const Imm32 &value,
                        const T &address, Register temp, Register output);
 
     template<typename T>
     void atomicFetchOp(int nbytes, bool signExtend, AtomicOp op, const Register &value,
                        const T &address, Register temp, Register output);
 
+    template<typename T>
+    void atomicEffectOpARMv6(int nbytes, AtomicOp op, const Register &value, const T &address);
+
+    template<typename T>
+    void atomicEffectOpARMv7(int nbytes, AtomicOp op, const Register &value, const T &address);
+
+    template<typename T>
+    void atomicEffectOp(int nbytes, AtomicOp op, const Imm32 &value, const T &address);
+
+    template<typename T>
+    void atomicEffectOp(int nbytes, AtomicOp op, const Register &value, const T &address);
+
   public:
     // T in {Address,BaseIndex}
     // S in {Imm32,Register}
 
     template<typename T>
     void compareExchange8SignExtend(const T &mem, Register oldval, Register newval, Register output)
     {
         compareExchange(1, true, mem, oldval, newval, output);
@@ -1538,16 +1550,28 @@ class MacroAssemblerARMCompat : public M
     template<typename T, typename S>
     void atomicFetchAdd16ZeroExtend(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(2, false, AtomicFetchAddOp, value, mem, temp, output);
     }
     template<typename T, typename S>
     void atomicFetchAdd32(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(4, false, AtomicFetchAddOp, value, mem, temp, output);
     }
+    template <typename T, typename S>
+    void atomicAdd8(const S &value, const T &mem) {
+        atomicEffectOp(1, AtomicFetchAddOp, value, mem);
+    }
+    template <typename T, typename S>
+    void atomicAdd16(const S &value, const T &mem) {
+        atomicEffectOp(2, AtomicFetchAddOp, value, mem);
+    }
+    template <typename T, typename S>
+    void atomicAdd32(const S &value, const T &mem) {
+        atomicEffectOp(4, AtomicFetchAddOp, value, mem);
+    }
 
     template<typename T, typename S>
     void atomicFetchSub8SignExtend(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(1, true, AtomicFetchSubOp, value, mem, temp, output);
     }
     template<typename T, typename S>
     void atomicFetchSub8ZeroExtend(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(1, false, AtomicFetchSubOp, value, mem, temp, output);
@@ -1559,16 +1583,28 @@ class MacroAssemblerARMCompat : public M
     template<typename T, typename S>
     void atomicFetchSub16ZeroExtend(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(2, false, AtomicFetchSubOp, value, mem, temp, output);
     }
     template<typename T, typename S>
     void atomicFetchSub32(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(4, false, AtomicFetchSubOp, value, mem, temp, output);
     }
+    template <typename T, typename S>
+    void atomicSub8(const S &value, const T &mem) {
+        atomicEffectOp(1, AtomicFetchSubOp, value, mem);
+    }
+    template <typename T, typename S>
+    void atomicSub16(const S &value, const T &mem) {
+        atomicEffectOp(2, AtomicFetchSubOp, value, mem);
+    }
+    template <typename T, typename S>
+    void atomicSub32(const S &value, const T &mem) {
+        atomicEffectOp(4, AtomicFetchSubOp, value, mem);
+    }
 
     template<typename T, typename S>
     void atomicFetchAnd8SignExtend(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(1, true, AtomicFetchAndOp, value, mem, temp, output);
     }
     template<typename T, typename S>
     void atomicFetchAnd8ZeroExtend(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(1, false, AtomicFetchAndOp, value, mem, temp, output);
@@ -1580,16 +1616,28 @@ class MacroAssemblerARMCompat : public M
     template<typename T, typename S>
     void atomicFetchAnd16ZeroExtend(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(2, false, AtomicFetchAndOp, value, mem, temp, output);
     }
     template<typename T, typename S>
     void atomicFetchAnd32(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(4, false, AtomicFetchAndOp, value, mem, temp, output);
     }
+    template <typename T, typename S>
+    void atomicAnd8(const S &value, const T &mem) {
+        atomicEffectOp(1, AtomicFetchAndOp, value, mem);
+    }
+    template <typename T, typename S>
+    void atomicAnd16(const S &value, const T &mem) {
+        atomicEffectOp(2, AtomicFetchAndOp, value, mem);
+    }
+    template <typename T, typename S>
+    void atomicAnd32(const S &value, const T &mem) {
+        atomicEffectOp(4, AtomicFetchAndOp, value, mem);
+    }
 
     template<typename T, typename S>
     void atomicFetchOr8SignExtend(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(1, true, AtomicFetchOrOp, value, mem, temp, output);
     }
     template<typename T, typename S>
     void atomicFetchOr8ZeroExtend(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(1, false, AtomicFetchOrOp, value, mem, temp, output);
@@ -1601,16 +1649,28 @@ class MacroAssemblerARMCompat : public M
     template<typename T, typename S>
     void atomicFetchOr16ZeroExtend(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(2, false, AtomicFetchOrOp, value, mem, temp, output);
     }
     template<typename T, typename S>
     void atomicFetchOr32(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(4, false, AtomicFetchOrOp, value, mem, temp, output);
     }
+    template <typename T, typename S>
+    void atomicOr8(const S &value, const T &mem) {
+        atomicEffectOp(1, AtomicFetchOrOp, value, mem);
+    }
+    template <typename T, typename S>
+    void atomicOr16(const S &value, const T &mem) {
+        atomicEffectOp(2, AtomicFetchOrOp, value, mem);
+    }
+    template <typename T, typename S>
+    void atomicOr32(const S &value, const T &mem) {
+        atomicEffectOp(4, AtomicFetchOrOp, value, mem);
+    }
 
     template<typename T, typename S>
     void atomicFetchXor8SignExtend(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(1, true, AtomicFetchXorOp, value, mem, temp, output);
     }
     template<typename T, typename S>
     void atomicFetchXor8ZeroExtend(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(1, false, AtomicFetchXorOp, value, mem, temp, output);
@@ -1622,16 +1682,28 @@ class MacroAssemblerARMCompat : public M
     template<typename T, typename S>
     void atomicFetchXor16ZeroExtend(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(2, false, AtomicFetchXorOp, value, mem, temp, output);
     }
     template<typename T, typename S>
     void atomicFetchXor32(const S &value, const T &mem, Register temp, Register output) {
         atomicFetchOp(4, false, AtomicFetchXorOp, value, mem, temp, output);
     }
+    template <typename T, typename S>
+    void atomicXor8(const S &value, const T &mem) {
+        atomicEffectOp(1, AtomicFetchXorOp, value, mem);
+    }
+    template <typename T, typename S>
+    void atomicXor16(const S &value, const T &mem) {
+        atomicEffectOp(2, AtomicFetchXorOp, value, mem);
+    }
+    template <typename T, typename S>
+    void atomicXor32(const S &value, const T &mem) {
+        atomicEffectOp(4, AtomicFetchXorOp, value, mem);
+    }
 
     void clampIntToUint8(Register reg) {
         // Look at (reg >> 8) if it is 0, then reg shouldn't be clamped if it is
         // <0, then we want to clamp to 0, otherwise, we wish to clamp to 255
         as_mov(ScratchRegister, asr(reg, 8), SetCond);
         ma_mov(Imm32(0xff), reg, NoSetCond, NotEqual);
         ma_mov(Imm32(0), reg, NoSetCond, Signed);
     }
--- a/js/src/jit/none/MacroAssembler-none.h
+++ b/js/src/jit/none/MacroAssembler-none.h
@@ -319,36 +319,51 @@ class MacroAssemblerNone : public Assemb
     template <typename T> void compareExchange16SignExtend(const T &mem, Register oldval, Register newval, Register output) { MOZ_CRASH(); }
     template <typename T> void compareExchange16ZeroExtend(const T &mem, Register oldval, Register newval, Register output) { MOZ_CRASH(); }
     template <typename T> void compareExchange32(const T &mem, Register oldval, Register newval, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchAdd8SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchAdd8ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchAdd16SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchAdd16ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchAdd32(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
+    template <typename T, typename S> void atomicAdd8(const T &value, const S &mem) { MOZ_CRASH(); }
+    template <typename T, typename S> void atomicAdd16(const T &value, const S &mem) { MOZ_CRASH(); }
+    template <typename T, typename S> void atomicAdd32(const T &value, const S &mem) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchSub8SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchSub8ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchSub16SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchSub16ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchSub32(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
+    template <typename T, typename S> void atomicSub8(const T &value, const S &mem) { MOZ_CRASH(); }
+    template <typename T, typename S> void atomicSub16(const T &value, const S &mem) { MOZ_CRASH(); }
+    template <typename T, typename S> void atomicSub32(const T &value, const S &mem) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchAnd8SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchAnd8ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchAnd16SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchAnd16ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchAnd32(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
+    template <typename T, typename S> void atomicAnd8(const T &value, const S &mem) { MOZ_CRASH(); }
+    template <typename T, typename S> void atomicAnd16(const T &value, const S &mem) { MOZ_CRASH(); }
+    template <typename T, typename S> void atomicAnd32(const T &value, const S &mem) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchOr8SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchOr8ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchOr16SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchOr16ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchOr32(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
+    template <typename T, typename S> void atomicOr8(const T &value, const S &mem) { MOZ_CRASH(); }
+    template <typename T, typename S> void atomicOr16(const T &value, const S &mem) { MOZ_CRASH(); }
+    template <typename T, typename S> void atomicOr32(const T &value, const S &mem) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchXor8SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchXor8ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchXor16SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchXor16ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
     template <typename T, typename S> void atomicFetchXor32(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); }
+    template <typename T, typename S> void atomicXor8(const T &value, const S &mem) { MOZ_CRASH(); }
+    template <typename T, typename S> void atomicXor16(const T &value, const S &mem) { MOZ_CRASH(); }
+    template <typename T, typename S> void atomicXor32(const T &value, const S &mem) { MOZ_CRASH(); }
 
     void clampIntToUint8(Register) { MOZ_CRASH(); }
 
     Register splitTagForTest(ValueOperand) { MOZ_CRASH(); }
 
     template <typename T> void branchTestUndefined(Condition, T, Label *) { MOZ_CRASH(); }
     template <typename T> void branchTestInt32(Condition, T, Label *) { MOZ_CRASH(); }
     template <typename T> void branchTestBoolean(Condition, T, Label *) { MOZ_CRASH(); }
--- a/js/src/jit/shared/MacroAssembler-x86-shared.h
+++ b/js/src/jit/shared/MacroAssembler-x86-shared.h
@@ -495,16 +495,79 @@ class MacroAssemblerX86Shared : public A
     }
     template <typename S, typename T>
     void atomicFetchXor32(const S &src, const T &mem, Register temp, Register output) {
         ATOMIC_BITOP_BODY(movl, xorl, lock_cmpxchgl)
     }
 
 #undef ATOMIC_BITOP_BODY
 
+    // S is Register or Imm32; T is Address or BaseIndex.
+
+    template <typename S, typename T>
+    void atomicAdd8(const S &src, const T &mem) {
+        lock_addb(src, Operand(mem));
+    }
+    template <typename S, typename T>
+    void atomicAdd16(const S &src, const T &mem) {
+        lock_addw(src, Operand(mem));
+    }
+    template <typename S, typename T>
+    void atomicAdd32(const S &src, const T &mem) {
+        lock_addl(src, Operand(mem));
+    }
+    template <typename S, typename T>
+    void atomicSub8(const S &src, const T &mem) {
+        lock_subb(src, Operand(mem));
+    }
+    template <typename S, typename T>
+    void atomicSub16(const S &src, const T &mem) {
+        lock_subw(src, Operand(mem));
+    }
+    template <typename S, typename T>
+    void atomicSub32(const S &src, const T &mem) {
+        lock_subl(src, Operand(mem));
+    }
+    template <typename S, typename T>
+    void atomicAnd8(const S &src, const T &mem) {
+        lock_andb(src, Operand(mem));
+    }
+    template <typename S, typename T>
+    void atomicAnd16(const S &src, const T &mem) {
+        lock_andw(src, Operand(mem));
+    }
+    template <typename S, typename T>
+    void atomicAnd32(const S &src, const T &mem) {
+        lock_andl(src, Operand(mem));
+    }
+    template <typename S, typename T>
+    void atomicOr8(const S &src, const T &mem) {
+        lock_orb(src, Operand(mem));
+    }
+    template <typename S, typename T>
+    void atomicOr16(const S &src, const T &mem) {
+        lock_orw(src, Operand(mem));
+    }
+    template <typename S, typename T>
+    void atomicOr32(const S &src, const T &mem) {
+        lock_orl(src, Operand(mem));
+    }
+    template <typename S, typename T>
+    void atomicXor8(const S &src, const T &mem) {
+        lock_xorb(src, Operand(mem));
+    }
+    template <typename S, typename T>
+    void atomicXor16(const S &src, const T &mem) {
+        lock_xorw(src, Operand(mem));
+    }
+    template <typename S, typename T>
+    void atomicXor32(const S &src, const T &mem) {
+        lock_xorl(src, Operand(mem));
+    }
+
     void storeLoadFence() {
         // This implementation follows Linux.
         if (HasSSE2())
             masm.mfence();
         else
             lock_addl(Imm32(0), Operand(Address(esp, 0)));
     }