Bug 988950 - Use scratch register instead of temp where possible r=jandem
authorJon Coppeard <jcoppeard@mozilla.com>
Wed, 23 Apr 2014 13:48:35 +0100
changeset 180115 174895f05c9f2ed25fc4454b344cc88ce207e2cf
parent 180114 13d60930dab2b563e9bdd9564f54775588914bf5
child 180116 691d410b7f59dff294f91c3fd34e5688fea154e9
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersjandem
bugs988950
milestone31.0a1
Bug 988950 - Use scratch register instead of temp where possible r=jandem
js/src/jit/CodeGenerator.cpp
js/src/jit/Lowering.cpp
js/src/jit/arm/Lowering-arm.h
js/src/jit/arm/MacroAssembler-arm.cpp
js/src/jit/x64/Lowering-x64.h
js/src/jit/x64/MacroAssembler-x64.cpp
js/src/jit/x86/Lowering-x86.h
js/src/jit/x86/MacroAssembler-x86.cpp
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -1826,17 +1826,17 @@ CodeGenerator::visitOutOfLineCallPostWri
 bool
 CodeGenerator::visitPostWriteBarrierO(LPostWriteBarrierO *lir)
 {
 #ifdef JSGC_GENERATIONAL
     OutOfLineCallPostWriteBarrier *ool = new(alloc()) OutOfLineCallPostWriteBarrier(lir, lir->object());
     if (!addOutOfLineCode(ool))
         return false;
 
-    Register temp = ToRegister(lir->temp());
+    Register temp = ToTempRegisterOrInvalid(lir->temp());
 
     if (lir->object()->isConstant()) {
         const Nursery &nursery = GetIonContext()->runtime->gcNursery();
         JS_ASSERT(!nursery.isInside(&lir->object()->toConstant()->toObject()));
     } else {
         masm.branchPtrInNurseryRange(ToRegister(lir->object()), temp, ool->rejoin());
     }
 
@@ -1850,17 +1850,17 @@ CodeGenerator::visitPostWriteBarrierO(LP
 bool
 CodeGenerator::visitPostWriteBarrierV(LPostWriteBarrierV *lir)
 {
 #ifdef JSGC_GENERATIONAL
     OutOfLineCallPostWriteBarrier *ool = new(alloc()) OutOfLineCallPostWriteBarrier(lir, lir->object());
     if (!addOutOfLineCode(ool))
         return false;
 
-    Register temp = ToRegister(lir->temp());
+    Register temp = ToTempRegisterOrInvalid(lir->temp());
 
     if (lir->object()->isConstant()) {
         const Nursery &nursery = GetIonContext()->runtime->gcNursery();
         JS_ASSERT(!nursery.isInside(&lir->object()->toConstant()->toObject()));
     } else {
         masm.branchPtrInNurseryRange(ToRegister(lir->object()), temp, ool->rejoin());
     }
 
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -2326,25 +2326,27 @@ LIRGenerator::visitMonitorTypes(MMonitor
 }
 
 bool
 LIRGenerator::visitPostWriteBarrier(MPostWriteBarrier *ins)
 {
 #ifdef JSGC_GENERATIONAL
     switch (ins->value()->type()) {
       case MIRType_Object: {
+        LDefinition tmp = needTempForObjectInNurseryRange() ? temp() : LDefinition::BogusTemp();
         LPostWriteBarrierO *lir =
             new(alloc()) LPostWriteBarrierO(useRegisterOrConstant(ins->object()),
-                                            useRegister(ins->value()),
-                                            temp());
+                                            useRegister(ins->value()), tmp);
         return add(lir, ins) && assignSafepoint(lir, ins);
       }
       case MIRType_Value: {
+        bool needTemp = needTempForObjectInNurseryRange() || needTempForValueIsNurseryObject();
+        LDefinition tmp = needTemp ? temp() : LDefinition::BogusTemp();
         LPostWriteBarrierV *lir =
-            new(alloc()) LPostWriteBarrierV(useRegisterOrConstant(ins->object()), temp());
+            new(alloc()) LPostWriteBarrierV(useRegisterOrConstant(ins->object()), tmp);
         if (!useBox(lir, LPostWriteBarrierV::Input, ins->value()))
             return false;
         return add(lir, ins) && assignSafepoint(lir, ins);
       }
       default:
         // Currently, only objects can be in the nursery. Other instruction
         // types cannot hold nursery pointers.
         return true;
--- a/js/src/jit/arm/Lowering-arm.h
+++ b/js/src/jit/arm/Lowering-arm.h
@@ -30,16 +30,19 @@ class LIRGeneratorARM : public LIRGenera
     // stores and loads; on ARM all registers are okay.
     LAllocation useByteOpRegister(MDefinition *mir);
     LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition *mir);
 
     inline LDefinition tempToUnbox() {
         return LDefinition::BogusTemp();
     }
 
+    bool needTempForObjectInNurseryRange() { return false; }
+    bool needTempForValueIsNurseryObject() { return false; }
+
     // x64 has a scratch register, so no need for another temp for dispatch
     // ICs.
     LDefinition tempForDispatchCache(MIRType outputType = MIRType_None) {
         return LDefinition::BogusTemp();
     }
 
     void lowerUntypedPhiInput(MPhi *phi, uint32_t inputPosition, LBlock *block, size_t lirIndex);
     bool defineUntypedPhi(MPhi *phi, size_t lirIndex);
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -4335,38 +4335,28 @@ MacroAssemblerARMCompat::jumpWithPatch(R
 }
 
 #ifdef JSGC_GENERATIONAL
 
 void
 MacroAssemblerARMCompat::branchPtrInNurseryRange(Register ptr, Register temp, Label *label)
 {
     JS_ASSERT(ptr != temp);
-    JS_ASSERT(temp != InvalidReg);
+    JS_ASSERT(ptr != ScratchRegister);
 
     const Nursery &nursery = GetIonContext()->runtime->gcNursery();
-    movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
-    addPtr(ptr, temp);
-    branchPtr(Assembler::Below, temp, Imm32(Nursery::NurserySize), label);
+    movePtr(ImmWord(-ptrdiff_t(nursery.start())), ScratchRegister);
+    addPtr(ptr, ScratchRegister);
+    branchPtr(Assembler::Below, ScratchRegister, Imm32(Nursery::NurserySize), label);
 }
 
 void
 MacroAssemblerARMCompat::branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label)
 {
     Label done;
 
     branchTestObject(Assembler::NotEqual, value, &done);
-
-    Register obj = extractObject(value, temp);
-    // valobj and temp may be the same register, in which case we mustn't trash it
-    // before we use its contents.
-    if (obj == temp) {
-        const Nursery &nursery = GetIonContext()->runtime->gcNursery();
-        addPtr(ImmWord(-ptrdiff_t(nursery.start())), obj);
-        branchPtr(Assembler::Below, obj, Imm32(Nursery::NurserySize), label);
-    } else {
-        branchPtrInNurseryRange(obj, temp, label);
-    }
+    branchPtrInNurseryRange(value.payloadReg(), temp, label);
 
     bind(&done);
 }
 
 #endif
--- a/js/src/jit/x64/Lowering-x64.h
+++ b/js/src/jit/x64/Lowering-x64.h
@@ -30,16 +30,19 @@ class LIRGeneratorX64 : public LIRGenera
 
     // x86 has constraints on what registers can be formatted for 1-byte
     // stores and loads; on x64 all registers are okay.
     LAllocation useByteOpRegister(MDefinition *mir);
     LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition *mir);
 
     LDefinition tempToUnbox();
 
+    bool needTempForObjectInNurseryRange() { return false; }
+    bool needTempForValueIsNurseryObject() { return true; }
+
     // x64 has a scratch register, so no need for another temp for dispatch
     // ICs.
     LDefinition tempForDispatchCache(MIRType outputType = MIRType_None) {
         return LDefinition::BogusTemp();
     }
 
   public:
     bool visitBox(MBox *box);
--- a/js/src/jit/x64/MacroAssembler-x64.cpp
+++ b/js/src/jit/x64/MacroAssembler-x64.cpp
@@ -384,33 +384,36 @@ MacroAssemblerX64::testNegativeZeroFloat
 }
 
 #ifdef JSGC_GENERATIONAL
 
 void
 MacroAssemblerX64::branchPtrInNurseryRange(Register ptr, Register temp, Label *label)
 {
     JS_ASSERT(ptr != temp);
-    JS_ASSERT(temp != InvalidReg);
+    JS_ASSERT(ptr != ScratchReg);
+    // temp may be InvalidReg.
 
     const Nursery &nursery = GetIonContext()->runtime->gcNursery();
-    movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
-    addPtr(ptr, temp);
-    branchPtr(Assembler::Below, temp, Imm32(Nursery::NurserySize), label);
+    movePtr(ImmWord(-ptrdiff_t(nursery.start())), ScratchReg);
+    addPtr(ptr, ScratchReg);
+    branchPtr(Assembler::Below, ScratchReg, Imm32(Nursery::NurserySize), label);
 }
 
 void
 MacroAssemblerX64::branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label)
 {
+    JS_ASSERT(temp != InvalidReg);
+
     Label done;
 
     branchTestObject(Assembler::NotEqual, value, &done);
 
     Register obj = extractObject(value, temp);
-    // valobj and temp may be the same register, in which case we mustn't trash it
+    // obj and temp may be the same register, in which case we mustn't trash it
     // before we use its contents.
     if (obj == temp) {
         const Nursery &nursery = GetIonContext()->runtime->gcNursery();
         addPtr(ImmWord(-ptrdiff_t(nursery.start())), obj);
         branchPtr(Assembler::Below, obj, Imm32(Nursery::NurserySize), label);
     } else {
         branchPtrInNurseryRange(obj, temp, label);
     }
--- a/js/src/jit/x86/Lowering-x86.h
+++ b/js/src/jit/x86/Lowering-x86.h
@@ -33,16 +33,19 @@ class LIRGeneratorX86 : public LIRGenera
     // give us one of {al,bl,cl,dl}. For now, just useFixed(al).
     LAllocation useByteOpRegister(MDefinition *mir);
     LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition *mir);
 
     inline LDefinition tempToUnbox() {
         return LDefinition::BogusTemp();
     }
 
+    bool needTempForObjectInNurseryRange() { return true; }
+    bool needTempForValueIsNurseryObject() { return true; }
+
     LDefinition tempForDispatchCache(MIRType outputType = MIRType_None);
 
     void lowerUntypedPhiInput(MPhi *phi, uint32_t inputPosition, LBlock *block, size_t lirIndex);
     bool defineUntypedPhi(MPhi *phi, size_t lirIndex);
 
   public:
     bool visitBox(MBox *box);
     bool visitUnbox(MUnbox *unbox);
--- a/js/src/jit/x86/MacroAssembler-x86.cpp
+++ b/js/src/jit/x86/MacroAssembler-x86.cpp
@@ -429,38 +429,28 @@ MacroAssemblerX86::testNegativeZeroFloat
 }
 
 #ifdef JSGC_GENERATIONAL
 
 void
 MacroAssemblerX86::branchPtrInNurseryRange(Register ptr, Register temp, Label *label)
 {
     JS_ASSERT(ptr != temp);
-    JS_ASSERT(temp != InvalidReg);
+    JS_ASSERT(temp != InvalidReg);  // A temp register is required for x86.
 
     const Nursery &nursery = GetIonContext()->runtime->gcNursery();
     movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
     addPtr(ptr, temp);
     branchPtr(Assembler::Below, temp, Imm32(Nursery::NurserySize), label);
 }
 
 void
 MacroAssemblerX86::branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label)
 {
     Label done;
 
     branchTestObject(Assembler::NotEqual, value, &done);
-
-    Register obj = extractObject(value, temp);
-    // valobj and temp may be the same register, in which case we mustn't trash it
-    // before we use its contents.
-    if (obj == temp) {
-        const Nursery &nursery = GetIonContext()->runtime->gcNursery();
-        addPtr(ImmWord(-ptrdiff_t(nursery.start())), obj);
-        branchPtr(Assembler::Below, obj, Imm32(Nursery::NurserySize), label);
-    } else {
-        branchPtrInNurseryRange(obj, temp, label);
-    }
+    branchPtrInNurseryRange(value.payloadReg(), temp, label);
 
     bind(&done);
 }
 
 #endif