Bug 1137291 - avoid clobbering an input register. r=h4writer
authorLars T Hansen <lhansen@mozilla.com>
Tue, 03 Mar 2015 10:47:00 +0100
changeset 246972 6f507d09cfec8692811f15cc87a070ea8c88ef5d
parent 246971 765a823e848aa576875462aae6c616075fdf446c
child 246973 d83e46943d92a5bcc3cc380159340079648b45d2
push id884
push userdburns@mozilla.com
push dateTue, 03 Mar 2015 15:29:12 +0000
reviewersh4writer
bugs1137291
milestone39.0a1
Bug 1137291 - avoid clobbering an input register. r=h4writer
js/src/jit/LIR-Common.h
js/src/jit/arm/CodeGenerator-arm.cpp
js/src/jit/shared/Lowering-x86-shared.cpp
js/src/jit/shared/Lowering-x86-shared.h
js/src/jit/x64/CodeGenerator-x64.cpp
js/src/jit/x64/Lowering-x64.cpp
js/src/jit/x64/Lowering-x64.h
js/src/jit/x86/CodeGenerator-x86.cpp
js/src/jit/x86/Lowering-x86.cpp
js/src/jit/x86/Lowering-x86.h
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -6374,64 +6374,80 @@ class LAsmJSStoreHeap : public LInstruct
     const LAllocation *ptr() {
         return getOperand(0);
     }
     const LAllocation *value() {
         return getOperand(1);
     }
 };
 
-class LAsmJSCompareExchangeHeap : public LInstructionHelper<1, 3, 0>
+class LAsmJSCompareExchangeHeap : public LInstructionHelper<1, 3, 1>
 {
   public:
     LIR_HEADER(AsmJSCompareExchangeHeap);
 
     LAsmJSCompareExchangeHeap(const LAllocation &ptr, const LAllocation &oldValue,
                               const LAllocation &newValue)
     {
         setOperand(0, ptr);
         setOperand(1, oldValue);
         setOperand(2, newValue);
+        setTemp(0, LDefinition::BogusTemp());
     }
 
     const LAllocation *ptr() {
         return getOperand(0);
     }
     const LAllocation *oldValue() {
         return getOperand(1);
     }
     const LAllocation *newValue() {
         return getOperand(2);
     }
+    const LDefinition *addrTemp() {
+        return getTemp(0);
+    }
+
+    void setAddrTemp(const LDefinition &addrTemp) {
+        setTemp(0, addrTemp);
+    }
 
     MAsmJSCompareExchangeHeap *mir() const {
         return mir_->toAsmJSCompareExchangeHeap();
     }
 };
 
-class LAsmJSAtomicBinopHeap : public LInstructionHelper<1, 2, 1>
+class LAsmJSAtomicBinopHeap : public LInstructionHelper<1, 2, 2>
 {
   public:
     LIR_HEADER(AsmJSAtomicBinopHeap);
     LAsmJSAtomicBinopHeap(const LAllocation &ptr, const LAllocation &value,
                           const LDefinition &temp)
     {
         setOperand(0, ptr);
         setOperand(1, value);
         setTemp(0, temp);
+        setTemp(1, LDefinition::BogusTemp());
     }
     const LAllocation *ptr() {
         return getOperand(0);
     }
     const LAllocation *value() {
         return getOperand(1);
     }
     const LDefinition *temp() {
         return getTemp(0);
     }
+    const LDefinition *addrTemp() {
+        return getTemp(1);
+    }
+
+    void setAddrTemp(const LDefinition &addrTemp) {
+        setTemp(1, addrTemp);
+    }
 
     MAsmJSAtomicBinopHeap *mir() const {
         return mir_->toAsmJSAtomicBinopHeap();
     }
 };
 
 class LAsmJSLoadGlobalVar : public LInstructionHelper<1, 0, 0>
 {
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -1923,16 +1923,17 @@ CodeGeneratorARM::visitAsmJSStoreHeap(LA
 void
 CodeGeneratorARM::visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap *ins)
 {
     MAsmJSCompareExchangeHeap *mir = ins->mir();
     Scalar::Type vt = mir->accessType();
     const LAllocation *ptr = ins->ptr();
     Register ptrReg = ToRegister(ptr);
     BaseIndex srcAddr(HeapReg, ptrReg, TimesOne);
+    MOZ_ASSERT(ins->addrTemp()->isBogusTemp());
 
     Register oldval = ToRegister(ins->oldValue());
     Register newval = ToRegister(ins->newValue());
 
     Label rejoin;
     uint32_t maybeCmpOffset = 0;
     if (mir->needsBoundsCheck()) {
         Label goahead;
@@ -1960,16 +1961,17 @@ CodeGeneratorARM::visitAsmJSAtomicBinopH
     MAsmJSAtomicBinopHeap *mir = ins->mir();
     Scalar::Type vt = mir->accessType();
     const LAllocation *ptr = ins->ptr();
     Register ptrReg = ToRegister(ptr);
     Register temp = ins->temp()->isBogusTemp() ? InvalidReg : ToRegister(ins->temp());
     const LAllocation* value = ins->value();
     AtomicOp op = mir->operation();
 
+    MOZ_ASSERT(ins->addrTemp()->isBogusTemp());
     BaseIndex srcAddr(HeapReg, ptrReg, TimesOne);
 
     Label rejoin;
     uint32_t maybeCmpOffset = 0;
     if (mir->needsBoundsCheck()) {
         Label goahead;
         BufferOffset bo = masm.ma_BoundsCheck(ptrReg);
         Register out = ToRegister(ins->output());
--- a/js/src/jit/shared/Lowering-x86-shared.cpp
+++ b/js/src/jit/shared/Lowering-x86-shared.cpp
@@ -504,17 +504,18 @@ LIRGeneratorX86Shared::visitAtomicTypedA
 
     if (fixedOutput)
         defineFixed(lir, ins, LAllocation(AnyRegister(eax)));
     else
         define(lir, ins);
 }
 
 void
-LIRGeneratorX86Shared::visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap *ins)
+LIRGeneratorX86Shared::lowerAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap *ins,
+						     const LDefinition& addrTemp)
 {
     MDefinition *ptr = ins->ptr();
     MOZ_ASSERT(ptr->type() == MIRType_Int32);
 
     bool byteArray = false;
     switch (ins->accessType()) {
       case Scalar::Int8:
       case Scalar::Uint8:
@@ -545,21 +546,23 @@ LIRGeneratorX86Shared::visitAsmJSCompare
     // Bug #1077036 describes some optimization opportunities.
 
     const LAllocation newval = byteArray ? useFixed(ins->newValue(), ebx) : useRegister(ins->newValue());
     const LAllocation oldval = useRegister(ins->oldValue());
 
     LAsmJSCompareExchangeHeap *lir =
         new(alloc()) LAsmJSCompareExchangeHeap(useRegister(ptr), oldval, newval);
 
+    lir->setAddrTemp(addrTemp);
     defineFixed(lir, ins, LAllocation(AnyRegister(eax)));
 }
 
 void
-LIRGeneratorX86Shared::visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap *ins)
+LIRGeneratorX86Shared::lowerAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap *ins,
+						 const LDefinition& addrTemp)
 {
     MDefinition *ptr = ins->ptr();
     MOZ_ASSERT(ptr->type() == MIRType_Int32);
 
     bool byteArray = false;
     switch (ins->accessType()) {
       case Scalar::Int8:
       case Scalar::Uint8:
@@ -623,16 +626,17 @@ LIRGeneratorX86Shared::visitAsmJSAtomicB
         value = useRegister(ins->value());
         if (bitOp)
             tempDef = temp();
     }
 
     LAsmJSAtomicBinopHeap *lir =
         new(alloc()) LAsmJSAtomicBinopHeap(useRegister(ptr), value, tempDef);
 
+    lir->setAddrTemp(addrTemp);
     defineFixed(lir, ins, LAllocation(AnyRegister(eax)));
 }
 
 void
 LIRGeneratorX86Shared::visitSimdBinaryArith(MSimdBinaryArith *ins)
 {
     MOZ_ASSERT(IsSimdType(ins->lhs()->type()));
     MOZ_ASSERT(IsSimdType(ins->rhs()->type()));
--- a/js/src/jit/shared/Lowering-x86-shared.h
+++ b/js/src/jit/shared/Lowering-x86-shared.h
@@ -53,16 +53,16 @@ class LIRGeneratorX86Shared : public LIR
     void lowerTruncateDToInt32(MTruncateToInt32 *ins);
     void lowerTruncateFToInt32(MTruncateToInt32 *ins);
     void visitSimdBinaryArith(MSimdBinaryArith *ins);
     void visitSimdSelect(MSimdSelect *ins);
     void visitSimdSplatX4(MSimdSplatX4 *ins);
     void visitSimdValueX4(MSimdValueX4 *ins);
     void visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement *ins);
     void visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop *ins);
-    void visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap *ins);
-    void visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap *ins);
+    void lowerAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap *ins, const LDefinition& addrTemp);
+    void lowerAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap *ins, const LDefinition& addrTemp);
 };
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_shared_Lowering_x86_shared_h */
--- a/js/src/jit/x64/CodeGenerator-x64.cpp
+++ b/js/src/jit/x64/CodeGenerator-x64.cpp
@@ -567,16 +567,17 @@ CodeGeneratorX64::visitAsmJSStoreHeap(LA
 
 void
 CodeGeneratorX64::visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap *ins)
 {
     MAsmJSCompareExchangeHeap *mir = ins->mir();
     Scalar::Type accessType = mir->accessType();
     const LAllocation *ptr = ins->ptr();
 
+    MOZ_ASSERT(ins->addrTemp()->isBogusTemp());
     MOZ_ASSERT(ptr->isRegister());
     BaseIndex srcAddr(HeapReg, ToRegister(ptr), TimesOne, mir->offset());
 
     Register oldval = ToRegister(ins->oldValue());
     Register newval = ToRegister(ins->newValue());
 
     // Note that we can't use
     // needsAsmJSBoundsCheckBranch/emitAsmJSBoundsCheckBranch/cleanupAfterAsmJSBoundsCheckBranch
@@ -613,16 +614,17 @@ CodeGeneratorX64::visitAsmJSAtomicBinopH
 {
     MAsmJSAtomicBinopHeap *mir = ins->mir();
     Scalar::Type accessType = mir->accessType();
     const LAllocation *ptr = ins->ptr();
     Register temp = ins->temp()->isBogusTemp() ? InvalidReg : ToRegister(ins->temp());
     const LAllocation* value = ins->value();
     AtomicOp op = mir->operation();
 
+    MOZ_ASSERT(ins->addrTemp()->isBogusTemp());
     MOZ_ASSERT(ptr->isRegister());
     BaseIndex srcAddr(HeapReg, ToRegister(ptr), TimesOne, mir->offset());
 
     // Note that we can't use
     // needsAsmJSBoundsCheckBranch/emitAsmJSBoundsCheckBranch/cleanupAfterAsmJSBoundsCheckBranch
     // since signal-handler bounds checking is not yet implemented for atomic accesses.
     Label rejoin;
     uint32_t maybeCmpOffset = AsmJSHeapAccess::NoLengthCheck;
--- a/js/src/jit/x64/Lowering-x64.cpp
+++ b/js/src/jit/x64/Lowering-x64.cpp
@@ -193,16 +193,28 @@ LIRGeneratorX64::visitAsmJSStoreHeap(MAs
       case Scalar::Uint8Clamped:
       case Scalar::MaxTypedArrayViewType:
         MOZ_CRASH("unexpected array type");
     }
     add(lir, ins);
 }
 
 void
+LIRGeneratorX64::visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap *ins)
+{
+    lowerAsmJSCompareExchangeHeap(ins, LDefinition::BogusTemp());
+}
+
+void
+LIRGeneratorX64::visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap *ins)
+{
+    lowerAsmJSAtomicBinopHeap(ins, LDefinition::BogusTemp());
+}
+
+void
 LIRGeneratorX64::visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr *ins)
 {
     define(new(alloc()) LAsmJSLoadFuncPtr(useRegister(ins->index()), temp()), ins);
 }
 
 void
 LIRGeneratorX64::visitSubstr(MSubstr *ins)
 {
--- a/js/src/jit/x64/Lowering-x64.h
+++ b/js/src/jit/x64/Lowering-x64.h
@@ -42,16 +42,18 @@ class LIRGeneratorX64 : public LIRGenera
     void visitBox(MBox *box);
     void visitUnbox(MUnbox *unbox);
     void visitReturn(MReturn *ret);
     void visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble *ins);
     void visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32 *ins);
     void visitAsmJSLoadHeap(MAsmJSLoadHeap *ins);
     void visitAsmJSStoreHeap(MAsmJSStoreHeap *ins);
     void visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr *ins);
+    void visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap *ins);
+    void visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap *ins);
     void visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic *ins);
     void visitSubstr(MSubstr *ins);
 };
 
 typedef LIRGeneratorX64 LIRGeneratorSpecific;
 
 } // namespace jit
 } // namespace js
--- a/js/src/jit/x86/CodeGenerator-x86.cpp
+++ b/js/src/jit/x86/CodeGenerator-x86.cpp
@@ -643,16 +643,17 @@ CodeGeneratorX86::visitAsmJSStoreHeap(LA
 void
 CodeGeneratorX86::visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap *ins)
 {
     MAsmJSCompareExchangeHeap *mir = ins->mir();
     Scalar::Type accessType = mir->accessType();
     const LAllocation *ptr = ins->ptr();
     Register oldval = ToRegister(ins->oldValue());
     Register newval = ToRegister(ins->newValue());
+    Register addrTemp = ToRegister(ins->addrTemp());
 
     MOZ_ASSERT(ptr->isRegister());
     // Set up the offset within the heap in the pointer reg.
     Register ptrReg = ToRegister(ptr);
 
     Label rejoin;
     uint32_t maybeCmpOffset = AsmJSHeapAccess::NoLengthCheck;
 
@@ -664,22 +665,23 @@ CodeGeneratorX86::visitAsmJSCompareExcha
         Register out = ToRegister(ins->output());
         masm.xorl(out,out);
         masm.jmp(&rejoin);
         masm.bind(&goahead);
     }
 
     // Add in the actual heap pointer explicitly, to avoid opening up
     // the abstraction that is compareExchangeToTypedIntArray at this time.
+    masm.movl(ptrReg, addrTemp);
     uint32_t before = masm.size();
-    masm.addlWithPatch(Imm32(mir->offset()), ptrReg);
+    masm.addlWithPatch(Imm32(mir->offset()), addrTemp);
     uint32_t after = masm.size();
     masm.append(AsmJSHeapAccess(before, after, maybeCmpOffset));
 
-    Address memAddr(ToRegister(ptr), mir->offset());
+    Address memAddr(addrTemp, mir->offset());
     masm.compareExchangeToTypedIntArray(accessType == Scalar::Uint32 ? Scalar::Int32 : accessType,
                                         memAddr,
                                         oldval,
                                         newval,
                                         InvalidReg,
                                         ToAnyRegister(ins->output()));
     if (rejoin.used())
         masm.bind(&rejoin);
@@ -687,16 +689,17 @@ CodeGeneratorX86::visitAsmJSCompareExcha
 
 void
 CodeGeneratorX86::visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap *ins)
 {
     MAsmJSAtomicBinopHeap *mir = ins->mir();
     Scalar::Type accessType = mir->accessType();
     const LAllocation *ptr = ins->ptr();
     Register temp = ins->temp()->isBogusTemp() ? InvalidReg : ToRegister(ins->temp());
+    Register addrTemp = ToRegister(ins->addrTemp());
     const LAllocation* value = ins->value();
     AtomicOp op = mir->operation();
 
     MOZ_ASSERT(ptr->isRegister());
     // Set up the offset within the heap in the pointer reg.
     Register ptrReg = ToRegister(ptr);
 
     Label rejoin;
@@ -710,22 +713,23 @@ CodeGeneratorX86::visitAsmJSAtomicBinopH
         Register out = ToRegister(ins->output());
         masm.xorl(out,out);
         masm.jmp(&rejoin);
         masm.bind(&goahead);
     }
 
     // Add in the actual heap pointer explicitly, to avoid opening up
     // the abstraction that is atomicBinopToTypedIntArray at this time.
+    masm.movl(ptrReg, addrTemp);
     uint32_t before = masm.size();
-    masm.addlWithPatch(Imm32(mir->offset()), ptrReg);
+    masm.addlWithPatch(Imm32(mir->offset()), addrTemp);
     uint32_t after = masm.size();
     masm.append(AsmJSHeapAccess(before, after, maybeCmpOffset));
 
-    Address memAddr(ptrReg, mir->offset());
+    Address memAddr(addrTemp, mir->offset());
     if (value->isConstant()) {
         masm.atomicBinopToTypedIntArray(op, accessType == Scalar::Uint32 ? Scalar::Int32 : accessType,
                                         Imm32(ToInt32(value)),
                                         memAddr,
                                         temp,
                                         InvalidReg,
                                         ToAnyRegister(ins->output()));
     } else {
--- a/js/src/jit/x86/Lowering-x86.cpp
+++ b/js/src/jit/x86/Lowering-x86.cpp
@@ -266,16 +266,28 @@ LIRGeneratorX86::visitStoreTypedArrayEle
         break;
       default: MOZ_CRASH("unexpected array type");
     }
 
     add(lir, ins);
 }
 
 void
+LIRGeneratorX86::visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap *ins)
+{
+    lowerAsmJSCompareExchangeHeap(ins, temp());
+}
+
+void
+LIRGeneratorX86::visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap *ins)
+{
+    lowerAsmJSAtomicBinopHeap(ins, temp());
+}
+
+void
 LIRGeneratorX86::visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr *ins)
 {
     define(new(alloc()) LAsmJSLoadFuncPtr(useRegisterAtStart(ins->index())), ins);
 }
 
 void
 LIRGeneratorX86::visitSubstr(MSubstr *ins)
 {
--- a/js/src/jit/x86/Lowering-x86.h
+++ b/js/src/jit/x86/Lowering-x86.h
@@ -48,16 +48,18 @@ class LIRGeneratorX86 : public LIRGenera
     void visitBox(MBox *box);
     void visitUnbox(MUnbox *unbox);
     void visitReturn(MReturn *ret);
     void visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble *ins);
     void visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32 *ins);
     void visitAsmJSLoadHeap(MAsmJSLoadHeap *ins);
     void visitAsmJSStoreHeap(MAsmJSStoreHeap *ins);
     void visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr *ins);
+    void visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap *ins);
+    void visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap *ins);
     void visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic *ins);
     void visitSubstr(MSubstr *ins);
     void lowerPhi(MPhi *phi);
 
     static bool allowTypedElementHoleCheck() {
         return true;
     }