mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-26 12:20:56 +00:00
Bug 1638295 - [MIPS] Support inlining Atomics functions for BigInt64/BigUint64.r=lth
Inline Atomics.load, Atomics.store, Atomics.compareExchange, Atomics.exchange and Atomics.{add,and,or,sub,xor}. Differential Revision: https://phabricator.services.mozilla.com/D107366
This commit is contained in:
parent
51709b916b
commit
cae2b31f7a
@ -3666,11 +3666,13 @@ class MacroAssembler : public MacroAssemblerSpecific {
|
||||
|
||||
void compareExchange64(const Synchronization& sync, const Address& mem,
|
||||
Register64 expected, Register64 replacement,
|
||||
Register64 output) DEFINED_ON(arm, arm64, x64, x86);
|
||||
Register64 output)
|
||||
DEFINED_ON(arm, arm64, x64, x86, mips64);
|
||||
|
||||
void compareExchange64(const Synchronization& sync, const BaseIndex& mem,
|
||||
Register64 expected, Register64 replacement,
|
||||
Register64 output) DEFINED_ON(arm, arm64, x64, x86);
|
||||
Register64 output)
|
||||
DEFINED_ON(arm, arm64, x64, x86, mips64);
|
||||
|
||||
// Exchange with memory. Return the value initially in memory.
|
||||
// MIPS: `valueTemp`, `offsetTemp` and `maskTemp` must be defined for 8-bit
|
||||
@ -3700,11 +3702,11 @@ class MacroAssembler : public MacroAssemblerSpecific {
|
||||
|
||||
void atomicExchange64(const Synchronization& sync, const Address& mem,
|
||||
Register64 value, Register64 output)
|
||||
DEFINED_ON(arm, arm64, x64, x86);
|
||||
DEFINED_ON(arm, arm64, x64, x86, mips64);
|
||||
|
||||
void atomicExchange64(const Synchronization& sync, const BaseIndex& mem,
|
||||
Register64 value, Register64 output)
|
||||
DEFINED_ON(arm, arm64, x64, x86);
|
||||
DEFINED_ON(arm, arm64, x64, x86, mips64);
|
||||
|
||||
// Read-modify-write with memory. Return the value in memory before the
|
||||
// operation.
|
||||
@ -3759,7 +3761,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
|
||||
|
||||
void atomicFetchOp64(const Synchronization& sync, AtomicOp op,
|
||||
Register64 value, const Address& mem, Register64 temp,
|
||||
Register64 output) DEFINED_ON(arm, arm64, x64);
|
||||
Register64 output) DEFINED_ON(arm, arm64, x64, mips64);
|
||||
|
||||
void atomicFetchOp64(const Synchronization& sync, AtomicOp op,
|
||||
const Address& value, const Address& mem,
|
||||
@ -3767,7 +3769,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
|
||||
|
||||
void atomicFetchOp64(const Synchronization& sync, AtomicOp op,
|
||||
Register64 value, const BaseIndex& mem, Register64 temp,
|
||||
Register64 output) DEFINED_ON(arm, arm64, x64);
|
||||
Register64 output) DEFINED_ON(arm, arm64, x64, mips64);
|
||||
|
||||
void atomicFetchOp64(const Synchronization& sync, AtomicOp op,
|
||||
const Address& value, const BaseIndex& mem,
|
||||
@ -3785,14 +3787,14 @@ class MacroAssembler : public MacroAssemblerSpecific {
|
||||
|
||||
void atomicEffectOp64(const Synchronization& sync, AtomicOp op,
|
||||
Register64 value, const Address& mem, Register64 temp)
|
||||
DEFINED_ON(arm, arm64);
|
||||
DEFINED_ON(arm, arm64, mips64);
|
||||
|
||||
void atomicEffectOp64(const Synchronization& sync, AtomicOp op,
|
||||
Register64 value, const BaseIndex& mem) DEFINED_ON(x64);
|
||||
|
||||
void atomicEffectOp64(const Synchronization& sync, AtomicOp op,
|
||||
Register64 value, const BaseIndex& mem, Register64 temp)
|
||||
DEFINED_ON(arm, arm64);
|
||||
DEFINED_ON(arm, arm64, mips64);
|
||||
|
||||
// 64-bit atomic load. On 64-bit systems, use regular load with
|
||||
// Synchronization::Load, not this method.
|
||||
|
@ -2168,30 +2168,113 @@ void CodeGenerator::visitAtomicExchangeTypedArrayElement(
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGenerator::visitAtomicLoad64(LAtomicLoad64* lir) { MOZ_CRASH("NYI"); }
|
||||
|
||||
void CodeGenerator::visitAtomicStore64(LAtomicStore64* lir) {
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
||||
void CodeGenerator::visitCompareExchangeTypedArrayElement64(
|
||||
LCompareExchangeTypedArrayElement64* lir) {
|
||||
MOZ_CRASH("NYI");
|
||||
Register elements = ToRegister(lir->elements());
|
||||
Register oldval = ToRegister(lir->oldval());
|
||||
Register newval = ToRegister(lir->newval());
|
||||
Register64 temp1 = ToRegister64(lir->temp1());
|
||||
Register64 temp2 = ToRegister64(lir->temp2());
|
||||
Register out = ToRegister(lir->output());
|
||||
Register64 tempOut(out);
|
||||
|
||||
Scalar::Type arrayType = lir->mir()->arrayType();
|
||||
|
||||
masm.loadBigInt64(oldval, temp1);
|
||||
masm.loadBigInt64(newval, tempOut);
|
||||
|
||||
if (lir->index()->isConstant()) {
|
||||
Address dest = ToAddress(elements, lir->index(), arrayType);
|
||||
masm.compareExchange64(Synchronization::Full(), dest, temp1, tempOut,
|
||||
temp2);
|
||||
} else {
|
||||
BaseIndex dest(elements, ToRegister(lir->index()),
|
||||
ScaleFromScalarType(arrayType));
|
||||
masm.compareExchange64(Synchronization::Full(), dest, temp1, tempOut,
|
||||
temp2);
|
||||
}
|
||||
|
||||
emitCreateBigInt(lir, arrayType, temp2, out, temp1.scratchReg());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitAtomicExchangeTypedArrayElement64(
|
||||
LAtomicExchangeTypedArrayElement64* lir) {
|
||||
MOZ_CRASH("NYI");
|
||||
Register elements = ToRegister(lir->elements());
|
||||
Register value = ToRegister(lir->value());
|
||||
Register64 temp1 = ToRegister64(lir->temp1());
|
||||
Register64 temp2 = Register64(ToRegister(lir->temp2()));
|
||||
Register out = ToRegister(lir->output());
|
||||
|
||||
Scalar::Type arrayType = lir->mir()->arrayType();
|
||||
|
||||
masm.loadBigInt64(value, temp1);
|
||||
|
||||
if (lir->index()->isConstant()) {
|
||||
Address dest = ToAddress(elements, lir->index(), arrayType);
|
||||
masm.atomicExchange64(Synchronization::Full(), dest, temp1, temp2);
|
||||
} else {
|
||||
BaseIndex dest(elements, ToRegister(lir->index()),
|
||||
ScaleFromScalarType(arrayType));
|
||||
masm.atomicExchange64(Synchronization::Full(), dest, temp1, temp2);
|
||||
}
|
||||
|
||||
emitCreateBigInt(lir, arrayType, temp2, out, temp1.scratchReg());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitAtomicTypedArrayElementBinop64(
|
||||
LAtomicTypedArrayElementBinop64* lir) {
|
||||
MOZ_CRASH("NYI");
|
||||
MOZ_ASSERT(lir->mir()->hasUses());
|
||||
|
||||
Register elements = ToRegister(lir->elements());
|
||||
Register value = ToRegister(lir->value());
|
||||
Register64 temp1 = ToRegister64(lir->temp1());
|
||||
Register64 temp2 = ToRegister64(lir->temp2());
|
||||
Register out = ToRegister(lir->output());
|
||||
Register64 tempOut = Register64(out);
|
||||
|
||||
Scalar::Type arrayType = lir->mir()->arrayType();
|
||||
AtomicOp atomicOp = lir->mir()->operation();
|
||||
|
||||
masm.loadBigInt64(value, temp1);
|
||||
|
||||
if (lir->index()->isConstant()) {
|
||||
Address dest = ToAddress(elements, lir->index(), arrayType);
|
||||
masm.atomicFetchOp64(Synchronization::Full(), atomicOp, temp1, dest,
|
||||
tempOut, temp2);
|
||||
} else {
|
||||
BaseIndex dest(elements, ToRegister(lir->index()),
|
||||
ScaleFromScalarType(arrayType));
|
||||
masm.atomicFetchOp64(Synchronization::Full(), atomicOp, temp1, dest,
|
||||
tempOut, temp2);
|
||||
}
|
||||
|
||||
emitCreateBigInt(lir, arrayType, temp2, out, temp1.scratchReg());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitAtomicTypedArrayElementBinopForEffect64(
|
||||
LAtomicTypedArrayElementBinopForEffect64* lir) {
|
||||
MOZ_CRASH("NYI");
|
||||
MOZ_ASSERT(!lir->mir()->hasUses());
|
||||
|
||||
Register elements = ToRegister(lir->elements());
|
||||
Register value = ToRegister(lir->value());
|
||||
Register64 temp1 = ToRegister64(lir->temp1());
|
||||
Register64 temp2 = ToRegister64(lir->temp2());
|
||||
|
||||
Scalar::Type arrayType = lir->mir()->arrayType();
|
||||
AtomicOp atomicOp = lir->mir()->operation();
|
||||
|
||||
masm.loadBigInt64(value, temp1);
|
||||
|
||||
if (lir->index()->isConstant()) {
|
||||
Address dest = ToAddress(elements, lir->index(), arrayType);
|
||||
masm.atomicEffectOp64(Synchronization::Full(), atomicOp, temp1, dest,
|
||||
temp2);
|
||||
} else {
|
||||
BaseIndex dest(elements, ToRegister(lir->index()),
|
||||
ScaleFromScalarType(arrayType));
|
||||
masm.atomicEffectOp64(Synchronization::Full(), atomicOp, temp1, dest,
|
||||
temp2);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGenerator::visitWasmCompareExchangeI64(LWasmCompareExchangeI64* lir) {
|
||||
|
@ -602,16 +602,23 @@ void LIRGenerator::visitCompareExchangeTypedArrayElement(
|
||||
const LAllocation index =
|
||||
useRegisterOrIndexConstant(ins->index(), ins->arrayType());
|
||||
|
||||
const LAllocation newval = useRegister(ins->newval());
|
||||
const LAllocation oldval = useRegister(ins->oldval());
|
||||
|
||||
if (Scalar::isBigIntType(ins->arrayType())) {
|
||||
MOZ_CRASH("NYI");
|
||||
LInt64Definition temp1 = tempInt64();
|
||||
LInt64Definition temp2 = tempInt64();
|
||||
|
||||
auto* lir = new (alloc()) LCompareExchangeTypedArrayElement64(
|
||||
elements, index, oldval, newval, temp1, temp2);
|
||||
define(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the target is a floating register then we need a temp at the
|
||||
// CodeGenerator level for creating the result.
|
||||
|
||||
const LAllocation newval = useRegister(ins->newval());
|
||||
const LAllocation oldval = useRegister(ins->oldval());
|
||||
|
||||
LDefinition outTemp = LDefinition::BogusTemp();
|
||||
LDefinition valueTemp = LDefinition::BogusTemp();
|
||||
LDefinition offsetTemp = LDefinition::BogusTemp();
|
||||
@ -637,8 +644,6 @@ void LIRGenerator::visitCompareExchangeTypedArrayElement(
|
||||
|
||||
void LIRGenerator::visitAtomicExchangeTypedArrayElement(
|
||||
MAtomicExchangeTypedArrayElement* ins) {
|
||||
MOZ_ASSERT(ins->arrayType() <= Scalar::Uint32);
|
||||
|
||||
MOZ_ASSERT(ins->elements()->type() == MIRType::Elements);
|
||||
MOZ_ASSERT(ins->index()->type() == MIRType::IntPtr);
|
||||
|
||||
@ -646,14 +651,24 @@ void LIRGenerator::visitAtomicExchangeTypedArrayElement(
|
||||
const LAllocation index =
|
||||
useRegisterOrIndexConstant(ins->index(), ins->arrayType());
|
||||
|
||||
const LAllocation value = useRegister(ins->value());
|
||||
|
||||
if (Scalar::isBigIntType(ins->arrayType())) {
|
||||
MOZ_CRASH("NYI");
|
||||
LInt64Definition temp1 = tempInt64();
|
||||
LDefinition temp2 = temp();
|
||||
|
||||
auto* lir = new (alloc()) LAtomicExchangeTypedArrayElement64(
|
||||
elements, index, value, temp1, temp2);
|
||||
define(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the target is a floating register then we need a temp at the
|
||||
// CodeGenerator level for creating the result.
|
||||
|
||||
const LAllocation value = useRegister(ins->value());
|
||||
MOZ_ASSERT(ins->arrayType() <= Scalar::Uint32);
|
||||
|
||||
LDefinition outTemp = LDefinition::BogusTemp();
|
||||
LDefinition valueTemp = LDefinition::BogusTemp();
|
||||
LDefinition offsetTemp = LDefinition::BogusTemp();
|
||||
@ -677,14 +692,6 @@ void LIRGenerator::visitAtomicExchangeTypedArrayElement(
|
||||
define(lir, ins);
|
||||
}
|
||||
|
||||
void LIRGeneratorMIPSShared::lowerAtomicLoad64(MLoadUnboxedScalar* ins) {
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
||||
void LIRGeneratorMIPSShared::lowerAtomicStore64(MStoreUnboxedScalar* ins) {
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
||||
void LIRGenerator::visitWasmCompareExchangeHeap(MWasmCompareExchangeHeap* ins) {
|
||||
MOZ_ASSERT(ins->base()->type() == MIRType::Int32);
|
||||
|
||||
@ -794,7 +801,27 @@ void LIRGenerator::visitAtomicTypedArrayElementBinop(
|
||||
const LAllocation value = useRegister(ins->value());
|
||||
|
||||
if (Scalar::isBigIntType(ins->arrayType())) {
|
||||
MOZ_CRASH("NYI");
|
||||
LInt64Definition temp1 = tempInt64();
|
||||
LInt64Definition temp2 = tempInt64();
|
||||
|
||||
// Case 1: the result of the operation is not used.
|
||||
//
|
||||
// We can omit allocating the result BigInt.
|
||||
|
||||
if (ins->isForEffect()) {
|
||||
auto* lir = new (alloc()) LAtomicTypedArrayElementBinopForEffect64(
|
||||
elements, index, value, temp1, temp2);
|
||||
add(lir, ins);
|
||||
return;
|
||||
}
|
||||
|
||||
// Case 2: the result of the operation is used.
|
||||
|
||||
auto* lir = new (alloc())
|
||||
LAtomicTypedArrayElementBinop64(elements, index, value, temp1, temp2);
|
||||
define(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
return;
|
||||
}
|
||||
|
||||
LDefinition valueTemp = LDefinition::BogusTemp();
|
||||
|
@ -69,9 +69,6 @@ class LIRGeneratorMIPSShared : public LIRGeneratorShared {
|
||||
void lowerBigIntLsh(MBigIntLsh* ins);
|
||||
void lowerBigIntRsh(MBigIntRsh* ins);
|
||||
|
||||
void lowerAtomicLoad64(MLoadUnboxedScalar* ins);
|
||||
void lowerAtomicStore64(MStoreUnboxedScalar* ins);
|
||||
|
||||
LTableSwitch* newLTableSwitch(const LAllocation& in,
|
||||
const LDefinition& inputCopy,
|
||||
MTableSwitch* ins);
|
||||
|
@ -514,3 +514,48 @@ void CodeGenerator::visitTestI64AndBranch(LTestI64AndBranch* lir) {
|
||||
|
||||
emitBranch(input.reg, Imm32(0), Assembler::NonZero, ifTrue, ifFalse);
|
||||
}
|
||||
|
||||
void CodeGenerator::visitAtomicLoad64(LAtomicLoad64* lir) {
|
||||
Register elements = ToRegister(lir->elements());
|
||||
Register temp = ToRegister(lir->temp());
|
||||
Register64 temp64 = ToRegister64(lir->temp64());
|
||||
Register out = ToRegister(lir->output());
|
||||
const MLoadUnboxedScalar* mir = lir->mir();
|
||||
|
||||
Scalar::Type storageType = mir->storageType();
|
||||
|
||||
auto sync = Synchronization::Load();
|
||||
masm.memoryBarrierBefore(sync);
|
||||
if (lir->index()->isConstant()) {
|
||||
Address source =
|
||||
ToAddress(elements, lir->index(), storageType, mir->offsetAdjustment());
|
||||
masm.load64(source, temp64);
|
||||
} else {
|
||||
BaseIndex source(elements, ToRegister(lir->index()),
|
||||
ScaleFromScalarType(storageType), mir->offsetAdjustment());
|
||||
masm.load64(source, temp64);
|
||||
}
|
||||
masm.memoryBarrierAfter(sync);
|
||||
emitCreateBigInt(lir, storageType, temp64, out, temp);
|
||||
}
|
||||
|
||||
void CodeGenerator::visitAtomicStore64(LAtomicStore64* lir) {
|
||||
Register elements = ToRegister(lir->elements());
|
||||
Register value = ToRegister(lir->value());
|
||||
Register64 temp1 = ToRegister64(lir->temp1());
|
||||
|
||||
Scalar::Type writeType = lir->mir()->writeType();
|
||||
|
||||
masm.loadBigInt64(value, temp1);
|
||||
auto sync = Synchronization::Store();
|
||||
masm.memoryBarrierBefore(sync);
|
||||
if (lir->index()->isConstant()) {
|
||||
Address dest = ToAddress(elements, lir->index(), writeType);
|
||||
masm.store64(temp1, dest);
|
||||
} else {
|
||||
BaseIndex dest(elements, ToRegister(lir->index()),
|
||||
ScaleFromScalarType(writeType));
|
||||
masm.store64(temp1, dest);
|
||||
}
|
||||
masm.memoryBarrierAfter(sync);
|
||||
}
|
||||
|
@ -88,6 +88,25 @@ void LIRGeneratorMIPS64::lowerBigIntMod(MBigIntMod* ins) {
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void LIRGeneratorMIPS64::lowerAtomicLoad64(MLoadUnboxedScalar* ins) {
|
||||
const LUse elements = useRegister(ins->elements());
|
||||
const LAllocation index =
|
||||
useRegisterOrIndexConstant(ins->index(), ins->storageType());
|
||||
|
||||
auto* lir = new (alloc()) LAtomicLoad64(elements, index, temp(), tempInt64());
|
||||
define(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void LIRGeneratorMIPS64::lowerAtomicStore64(MStoreUnboxedScalar* ins) {
|
||||
LUse elements = useRegister(ins->elements());
|
||||
LAllocation index =
|
||||
useRegisterOrIndexConstant(ins->index(), ins->writeType());
|
||||
LAllocation value = useRegister(ins->value());
|
||||
|
||||
add(new (alloc()) LAtomicStore64(elements, index, value, tempInt64()), ins);
|
||||
}
|
||||
|
||||
void LIRGenerator::visitBox(MBox* box) {
|
||||
MDefinition* opd = box->getOperand(0);
|
||||
|
||||
|
@ -43,6 +43,9 @@ class LIRGeneratorMIPS64 : public LIRGeneratorMIPSShared {
|
||||
|
||||
void lowerBigIntDiv(MBigIntDiv* ins);
|
||||
void lowerBigIntMod(MBigIntMod* ins);
|
||||
|
||||
void lowerAtomicLoad64(MLoadUnboxedScalar* ins);
|
||||
void lowerAtomicStore64(MStoreUnboxedScalar* ins);
|
||||
};
|
||||
|
||||
typedef LIRGeneratorMIPS64 LIRGeneratorSpecific;
|
||||
|
@ -2561,20 +2561,24 @@ void MacroAssemblerMIPS64Compat::wasmStoreI64Impl(
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void WasmCompareExchange64(MacroAssembler& masm,
|
||||
const wasm::MemoryAccessDesc& access,
|
||||
const T& mem, Register64 expect,
|
||||
Register64 replace, Register64 output) {
|
||||
static void CompareExchange64(MacroAssembler& masm,
|
||||
const wasm::MemoryAccessDesc* access,
|
||||
const Synchronization& sync, const T& mem,
|
||||
Register64 expect, Register64 replace,
|
||||
Register64 output) {
|
||||
MOZ_ASSERT(oldval != output && newval != output);
|
||||
masm.computeEffectiveAddress(mem, SecondScratchReg);
|
||||
|
||||
Label tryAgain;
|
||||
Label exit;
|
||||
|
||||
masm.memoryBarrierBefore(access.sync());
|
||||
masm.memoryBarrierBefore(sync);
|
||||
|
||||
masm.bind(&tryAgain);
|
||||
|
||||
masm.append(access, masm.size());
|
||||
if (access) {
|
||||
masm.append(*access, masm.size());
|
||||
}
|
||||
masm.as_lld(output.reg, SecondScratchReg, 0);
|
||||
|
||||
masm.ma_b(output.reg, expect.reg, &exit, Assembler::NotEqual, ShortJump);
|
||||
@ -2583,7 +2587,7 @@ static void WasmCompareExchange64(MacroAssembler& masm,
|
||||
masm.ma_b(ScratchRegister, ScratchRegister, &tryAgain, Assembler::Zero,
|
||||
ShortJump);
|
||||
|
||||
masm.memoryBarrierAfter(access.sync());
|
||||
masm.memoryBarrierAfter(sync);
|
||||
|
||||
masm.bind(&exit);
|
||||
}
|
||||
@ -2593,7 +2597,8 @@ void MacroAssembler::wasmCompareExchange64(const wasm::MemoryAccessDesc& access,
|
||||
Register64 expect,
|
||||
Register64 replace,
|
||||
Register64 output) {
|
||||
WasmCompareExchange64(*this, access, mem, expect, replace, output);
|
||||
CompareExchange64(*this, &access, access.sync(), mem, expect, replace,
|
||||
output);
|
||||
}
|
||||
|
||||
void MacroAssembler::wasmCompareExchange64(const wasm::MemoryAccessDesc& access,
|
||||
@ -2601,58 +2606,100 @@ void MacroAssembler::wasmCompareExchange64(const wasm::MemoryAccessDesc& access,
|
||||
Register64 expect,
|
||||
Register64 replace,
|
||||
Register64 output) {
|
||||
WasmCompareExchange64(*this, access, mem, expect, replace, output);
|
||||
CompareExchange64(*this, &access, access.sync(), mem, expect, replace,
|
||||
output);
|
||||
}
|
||||
|
||||
void MacroAssembler::compareExchange64(const Synchronization& sync,
|
||||
const Address& mem, Register64 expect,
|
||||
Register64 replace, Register64 output) {
|
||||
CompareExchange64(*this, nullptr, sync, mem, expect, replace, output);
|
||||
}
|
||||
|
||||
void MacroAssembler::compareExchange64(const Synchronization& sync,
|
||||
const BaseIndex& mem, Register64 expect,
|
||||
Register64 replace, Register64 output) {
|
||||
CompareExchange64(*this, nullptr, sync, mem, expect, replace, output);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void AtomicExchange64(MacroAssembler& masm,
|
||||
const wasm::MemoryAccessDesc& access, const T& mem,
|
||||
Register64 src, Register64 output) {
|
||||
const wasm::MemoryAccessDesc* access,
|
||||
const Synchronization& sync, const T& mem,
|
||||
Register64 value, Register64 output) {
|
||||
MOZ_ASSERT(value != output);
|
||||
masm.computeEffectiveAddress(mem, SecondScratchReg);
|
||||
|
||||
Label tryAgain;
|
||||
|
||||
masm.memoryBarrierBefore(access.sync());
|
||||
masm.memoryBarrierBefore(sync);
|
||||
|
||||
masm.bind(&tryAgain);
|
||||
|
||||
masm.append(access, masm.size());
|
||||
masm.as_lld(output.reg, SecondScratchReg, 0);
|
||||
if (access) {
|
||||
masm.append(*access, masm.size());
|
||||
}
|
||||
|
||||
masm.movePtr(src.reg, ScratchRegister);
|
||||
masm.as_lld(output.reg, SecondScratchReg, 0);
|
||||
masm.movePtr(value.reg, ScratchRegister);
|
||||
masm.as_scd(ScratchRegister, SecondScratchReg, 0);
|
||||
masm.ma_b(ScratchRegister, ScratchRegister, &tryAgain, Assembler::Zero,
|
||||
ShortJump);
|
||||
|
||||
masm.memoryBarrierAfter(access.sync());
|
||||
masm.memoryBarrierAfter(sync);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void WasmAtomicExchange64(MacroAssembler& masm,
|
||||
const wasm::MemoryAccessDesc& access,
|
||||
const T& mem, Register64 value,
|
||||
Register64 output) {
|
||||
AtomicExchange64(masm, &access, access.sync(), mem, value, output);
|
||||
}
|
||||
|
||||
void MacroAssembler::wasmAtomicExchange64(const wasm::MemoryAccessDesc& access,
|
||||
const Address& mem, Register64 src,
|
||||
Register64 output) {
|
||||
AtomicExchange64(*this, access, mem, src, output);
|
||||
WasmAtomicExchange64(*this, access, mem, src, output);
|
||||
}
|
||||
|
||||
void MacroAssembler::wasmAtomicExchange64(const wasm::MemoryAccessDesc& access,
|
||||
const BaseIndex& mem, Register64 src,
|
||||
Register64 output) {
|
||||
AtomicExchange64(*this, access, mem, src, output);
|
||||
WasmAtomicExchange64(*this, access, mem, src, output);
|
||||
}
|
||||
|
||||
void MacroAssembler::atomicExchange64(const Synchronization& sync,
|
||||
const Address& mem, Register64 value,
|
||||
Register64 output) {
|
||||
AtomicExchange64(*this, nullptr, sync, mem, value, output);
|
||||
}
|
||||
|
||||
void MacroAssembler::atomicExchange64(const Synchronization& sync,
|
||||
const BaseIndex& mem, Register64 value,
|
||||
Register64 output) {
|
||||
AtomicExchange64(*this, nullptr, sync, mem, value, output);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void AtomicFetchOp64(MacroAssembler& masm,
|
||||
const wasm::MemoryAccessDesc& access, AtomicOp op,
|
||||
const wasm::MemoryAccessDesc* access,
|
||||
const Synchronization& sync, AtomicOp op,
|
||||
Register64 value, const T& mem, Register64 temp,
|
||||
Register64 output) {
|
||||
MOZ_ASSERT(value != output);
|
||||
MOZ_ASSERT(value != temp);
|
||||
masm.computeEffectiveAddress(mem, SecondScratchReg);
|
||||
|
||||
Label tryAgain;
|
||||
|
||||
masm.memoryBarrierBefore(access.sync());
|
||||
masm.memoryBarrierBefore(sync);
|
||||
|
||||
masm.bind(&tryAgain);
|
||||
if (access) {
|
||||
masm.append(*access, masm.size());
|
||||
}
|
||||
|
||||
masm.append(access, masm.size());
|
||||
masm.as_lld(output.reg, SecondScratchReg, 0);
|
||||
|
||||
switch (op) {
|
||||
@ -2678,21 +2725,45 @@ static void AtomicFetchOp64(MacroAssembler& masm,
|
||||
masm.as_scd(temp.reg, SecondScratchReg, 0);
|
||||
masm.ma_b(temp.reg, temp.reg, &tryAgain, Assembler::Zero, ShortJump);
|
||||
|
||||
masm.memoryBarrierAfter(access.sync());
|
||||
masm.memoryBarrierAfter(sync);
|
||||
}
|
||||
|
||||
void MacroAssembler::wasmAtomicFetchOp64(const wasm::MemoryAccessDesc& access,
|
||||
AtomicOp op, Register64 value,
|
||||
const Address& mem, Register64 temp,
|
||||
Register64 output) {
|
||||
AtomicFetchOp64(*this, access, op, value, mem, temp, output);
|
||||
AtomicFetchOp64(*this, &access, access.sync(), op, value, mem, temp, output);
|
||||
}
|
||||
|
||||
void MacroAssembler::wasmAtomicFetchOp64(const wasm::MemoryAccessDesc& access,
|
||||
AtomicOp op, Register64 value,
|
||||
const BaseIndex& mem, Register64 temp,
|
||||
Register64 output) {
|
||||
AtomicFetchOp64(*this, access, op, value, mem, temp, output);
|
||||
AtomicFetchOp64(*this, &access, access.sync(), op, value, mem, temp, output);
|
||||
}
|
||||
|
||||
void MacroAssembler::atomicFetchOp64(const Synchronization& sync, AtomicOp op,
|
||||
Register64 value, const Address& mem,
|
||||
Register64 temp, Register64 output) {
|
||||
AtomicFetchOp64(*this, nullptr, sync, op, value, mem, temp, output);
|
||||
}
|
||||
|
||||
void MacroAssembler::atomicFetchOp64(const Synchronization& sync, AtomicOp op,
|
||||
Register64 value, const BaseIndex& mem,
|
||||
Register64 temp, Register64 output) {
|
||||
AtomicFetchOp64(*this, nullptr, sync, op, value, mem, temp, output);
|
||||
}
|
||||
|
||||
void MacroAssembler::atomicEffectOp64(const Synchronization& sync, AtomicOp op,
|
||||
Register64 value, const Address& mem,
|
||||
Register64 temp) {
|
||||
AtomicFetchOp64(*this, nullptr, sync, op, value, mem, temp, temp);
|
||||
}
|
||||
|
||||
void MacroAssembler::atomicEffectOp64(const Synchronization& sync, AtomicOp op,
|
||||
Register64 value, const BaseIndex& mem,
|
||||
Register64 temp) {
|
||||
AtomicFetchOp64(*this, nullptr, sync, op, value, mem, temp, temp);
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
|
Loading…
x
Reference in New Issue
Block a user