diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp index f1cbe392db5..df67c79421b 100644 --- a/js/src/jit/MacroAssembler.cpp +++ b/js/src/jit/MacroAssembler.cpp @@ -642,6 +642,98 @@ 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 +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 void MacroAssembler::loadUnboxedProperty(T address, JSValueType type, TypedOrValueRegister output) diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h index 79039b0284d..33028e19e93 100644 --- a/js/src/jit/MacroAssembler.h +++ b/js/src/jit/MacroAssembler.h @@ -748,10 +748,15 @@ class MacroAssembler : public MacroAssemblerSpecific void compareExchangeToTypedIntArray(Scalar::Type arrayType, const T &mem, Register oldval, Register newval, Register temp, AnyRegister output); + // Generating a result. template void atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType, const S &value, const T &mem, Register temp1, Register temp2, AnyRegister output); + // Generating no result. + template + 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); diff --git a/js/src/jit/arm/MacroAssembler-arm.h b/js/src/jit/arm/MacroAssembler-arm.h index 29d473a50f2..6cf13ad98e9 100644 --- a/js/src/jit/arm/MacroAssembler-arm.h +++ b/js/src/jit/arm/MacroAssembler-arm.h @@ -1494,6 +1494,18 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM void atomicFetchOp(int nbytes, bool signExtend, AtomicOp op, const Register &value, const T &address, Register temp, Register output); + template + void atomicEffectOpARMv6(int nbytes, AtomicOp op, const Register &value, const T &address); + + template + void atomicEffectOpARMv7(int nbytes, AtomicOp op, const Register &value, const T &address); + + template + void atomicEffectOp(int nbytes, AtomicOp op, const Imm32 &value, const T &address); + + template + void atomicEffectOp(int nbytes, AtomicOp op, const Register &value, const T &address); + public: // T in {Address,BaseIndex} // S in {Imm32,Register} @@ -1543,6 +1555,18 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM void atomicFetchAdd32(const S &value, const T &mem, Register temp, Register output) { atomicFetchOp(4, false, AtomicFetchAddOp, value, mem, temp, output); } + template + void atomicAdd8(const S &value, const T &mem) { + atomicEffectOp(1, AtomicFetchAddOp, value, mem); + } + template + void atomicAdd16(const S &value, const T &mem) { + atomicEffectOp(2, AtomicFetchAddOp, value, mem); + } + template + void atomicAdd32(const S &value, const T &mem) { + atomicEffectOp(4, AtomicFetchAddOp, value, mem); + } template void atomicFetchSub8SignExtend(const S &value, const T &mem, Register temp, Register output) { @@ -1564,6 +1588,18 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM void atomicFetchSub32(const S &value, const T &mem, Register temp, Register output) { atomicFetchOp(4, false, AtomicFetchSubOp, value, mem, temp, output); } + template + void atomicSub8(const S &value, const T &mem) { + atomicEffectOp(1, AtomicFetchSubOp, value, mem); + } + template + void atomicSub16(const S &value, const T &mem) { + atomicEffectOp(2, AtomicFetchSubOp, value, mem); + } + template + void atomicSub32(const S &value, const T &mem) { + atomicEffectOp(4, AtomicFetchSubOp, value, mem); + } template void atomicFetchAnd8SignExtend(const S &value, const T &mem, Register temp, Register output) { @@ -1585,6 +1621,18 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM void atomicFetchAnd32(const S &value, const T &mem, Register temp, Register output) { atomicFetchOp(4, false, AtomicFetchAndOp, value, mem, temp, output); } + template + void atomicAnd8(const S &value, const T &mem) { + atomicEffectOp(1, AtomicFetchAndOp, value, mem); + } + template + void atomicAnd16(const S &value, const T &mem) { + atomicEffectOp(2, AtomicFetchAndOp, value, mem); + } + template + void atomicAnd32(const S &value, const T &mem) { + atomicEffectOp(4, AtomicFetchAndOp, value, mem); + } template void atomicFetchOr8SignExtend(const S &value, const T &mem, Register temp, Register output) { @@ -1606,6 +1654,18 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM void atomicFetchOr32(const S &value, const T &mem, Register temp, Register output) { atomicFetchOp(4, false, AtomicFetchOrOp, value, mem, temp, output); } + template + void atomicOr8(const S &value, const T &mem) { + atomicEffectOp(1, AtomicFetchOrOp, value, mem); + } + template + void atomicOr16(const S &value, const T &mem) { + atomicEffectOp(2, AtomicFetchOrOp, value, mem); + } + template + void atomicOr32(const S &value, const T &mem) { + atomicEffectOp(4, AtomicFetchOrOp, value, mem); + } template void atomicFetchXor8SignExtend(const S &value, const T &mem, Register temp, Register output) { @@ -1627,6 +1687,18 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM void atomicFetchXor32(const S &value, const T &mem, Register temp, Register output) { atomicFetchOp(4, false, AtomicFetchXorOp, value, mem, temp, output); } + template + void atomicXor8(const S &value, const T &mem) { + atomicEffectOp(1, AtomicFetchXorOp, value, mem); + } + template + void atomicXor16(const S &value, const T &mem) { + atomicEffectOp(2, AtomicFetchXorOp, value, mem); + } + template + 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 diff --git a/js/src/jit/none/MacroAssembler-none.h b/js/src/jit/none/MacroAssembler-none.h index 212c4843306..7b224121fd7 100644 --- a/js/src/jit/none/MacroAssembler-none.h +++ b/js/src/jit/none/MacroAssembler-none.h @@ -324,26 +324,41 @@ class MacroAssemblerNone : public Assembler template void atomicFetchAdd16SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchAdd16ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchAdd32(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } + template void atomicAdd8(const T &value, const S &mem) { MOZ_CRASH(); } + template void atomicAdd16(const T &value, const S &mem) { MOZ_CRASH(); } + template void atomicAdd32(const T &value, const S &mem) { MOZ_CRASH(); } template void atomicFetchSub8SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchSub8ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchSub16SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchSub16ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchSub32(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } + template void atomicSub8(const T &value, const S &mem) { MOZ_CRASH(); } + template void atomicSub16(const T &value, const S &mem) { MOZ_CRASH(); } + template void atomicSub32(const T &value, const S &mem) { MOZ_CRASH(); } template void atomicFetchAnd8SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchAnd8ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchAnd16SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchAnd16ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchAnd32(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } + template void atomicAnd8(const T &value, const S &mem) { MOZ_CRASH(); } + template void atomicAnd16(const T &value, const S &mem) { MOZ_CRASH(); } + template void atomicAnd32(const T &value, const S &mem) { MOZ_CRASH(); } template void atomicFetchOr8SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchOr8ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchOr16SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchOr16ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchOr32(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } + template void atomicOr8(const T &value, const S &mem) { MOZ_CRASH(); } + template void atomicOr16(const T &value, const S &mem) { MOZ_CRASH(); } + template void atomicOr32(const T &value, const S &mem) { MOZ_CRASH(); } template void atomicFetchXor8SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchXor8ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchXor16SignExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchXor16ZeroExtend(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } template void atomicFetchXor32(const T &value, const S &mem, Register temp, Register output) { MOZ_CRASH(); } + template void atomicXor8(const T &value, const S &mem) { MOZ_CRASH(); } + template void atomicXor16(const T &value, const S &mem) { MOZ_CRASH(); } + template void atomicXor32(const T &value, const S &mem) { MOZ_CRASH(); } void clampIntToUint8(Register) { MOZ_CRASH(); } diff --git a/js/src/jit/shared/MacroAssembler-x86-shared.h b/js/src/jit/shared/MacroAssembler-x86-shared.h index c6f393447b3..cf46881ed47 100644 --- a/js/src/jit/shared/MacroAssembler-x86-shared.h +++ b/js/src/jit/shared/MacroAssembler-x86-shared.h @@ -500,6 +500,69 @@ class MacroAssemblerX86Shared : public Assembler #undef ATOMIC_BITOP_BODY + // S is Register or Imm32; T is Address or BaseIndex. + + template + void atomicAdd8(const S &src, const T &mem) { + lock_addb(src, Operand(mem)); + } + template + void atomicAdd16(const S &src, const T &mem) { + lock_addw(src, Operand(mem)); + } + template + void atomicAdd32(const S &src, const T &mem) { + lock_addl(src, Operand(mem)); + } + template + void atomicSub8(const S &src, const T &mem) { + lock_subb(src, Operand(mem)); + } + template + void atomicSub16(const S &src, const T &mem) { + lock_subw(src, Operand(mem)); + } + template + void atomicSub32(const S &src, const T &mem) { + lock_subl(src, Operand(mem)); + } + template + void atomicAnd8(const S &src, const T &mem) { + lock_andb(src, Operand(mem)); + } + template + void atomicAnd16(const S &src, const T &mem) { + lock_andw(src, Operand(mem)); + } + template + void atomicAnd32(const S &src, const T &mem) { + lock_andl(src, Operand(mem)); + } + template + void atomicOr8(const S &src, const T &mem) { + lock_orb(src, Operand(mem)); + } + template + void atomicOr16(const S &src, const T &mem) { + lock_orw(src, Operand(mem)); + } + template + void atomicOr32(const S &src, const T &mem) { + lock_orl(src, Operand(mem)); + } + template + void atomicXor8(const S &src, const T &mem) { + lock_xorb(src, Operand(mem)); + } + template + void atomicXor16(const S &src, const T &mem) { + lock_xorw(src, Operand(mem)); + } + template + void atomicXor32(const S &src, const T &mem) { + lock_xorl(src, Operand(mem)); + } + void storeLoadFence() { // This implementation follows Linux. if (HasSSE2())