Bug 880471: IonMonkey: Remove the request for unused temp. variable for x86/arm unboxing, r=jandem
authorHannes Verschore <hv1989@gmail.com>
Tue, 18 Jun 2013 11:43:34 +0200
changeset 135451 e9e7d8066cb940fd97acd95a494f1d043c1bab57
parent 135450 db02f2b140d22ca39b64c69b509e400c0c600723
child 135452 b2d1e90f21a2cd5108e511e82cf6232891d2d7af
push id24841
push userryanvm@gmail.com
push dateTue, 18 Jun 2013 23:04:53 +0000
treeherdermozilla-central@d2a7cfa34154 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs880471
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 880471: IonMonkey: Remove the request for unused temp. variable for x86/arm unboxing, r=jandem
js/src/ion/CodeGenerator.cpp
js/src/ion/IonMacroAssembler.cpp
js/src/ion/LIR-Common.h
js/src/ion/Lowering.cpp
js/src/ion/arm/Lowering-arm.h
js/src/ion/shared/CodeGenerator-shared-inl.h
js/src/ion/x64/Lowering-x64.h
js/src/ion/x86/Lowering-x86.h
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -1134,32 +1134,32 @@ CodeGenerator::visitParDump(LParDump *li
     masm.freeStack(sizeof(Value));
     return true;
 }
 
 bool
 CodeGenerator::visitTypeBarrier(LTypeBarrier *lir)
 {
     ValueOperand operand = ToValue(lir, LTypeBarrier::Input);
-    Register scratch = ToRegister(lir->temp());
+    Register scratch = ToTempUnboxRegister(lir->temp());
 
     Label matched, miss;
     masm.guardTypeSet(operand, lir->mir()->resultTypeSet(), scratch, &matched, &miss);
     masm.jump(&miss);
     if (!bailoutFrom(&miss, lir->snapshot()))
         return false;
     masm.bind(&matched);
     return true;
 }
 
 bool
 CodeGenerator::visitMonitorTypes(LMonitorTypes *lir)
 {
     ValueOperand operand = ToValue(lir, LMonitorTypes::Input);
-    Register scratch = ToRegister(lir->temp());
+    Register scratch = ToTempUnboxRegister(lir->temp());
 
     Label matched, miss;
     masm.guardTypeSet(operand, lir->mir()->typeSet(), scratch, &matched, &miss);
     masm.jump(&miss);
     if (!bailoutFrom(&miss, lir->snapshot()))
         return false;
     masm.bind(&matched);
     return true;
@@ -1283,17 +1283,17 @@ CodeGenerator::visitPostWriteBarrierV(LP
     } else {
         Label tenured;
         Register objreg = ToRegister(lir->object());
         masm.branchPtr(Assembler::Below, objreg, ImmWord(nursery.start()), &tenured);
         masm.branchPtr(Assembler::Below, objreg, ImmWord(nursery.heapEnd()), ool->rejoin());
         masm.bind(&tenured);
     }
 
-    Register valuereg = masm.extractObject(value, ToRegister(lir->temp()));
+    Register valuereg = masm.extractObject(value, ToTempUnboxRegister(lir->temp()));
     masm.branchPtr(Assembler::Below, valuereg, ImmWord(nursery.start()), ool->rejoin());
     masm.branchPtr(Assembler::Below, valuereg, ImmWord(nursery.heapEnd()), ool->entry());
 
     masm.bind(ool->rejoin());
 #endif
     return true;
 }
 
@@ -3539,26 +3539,27 @@ bool
 CodeGenerator::visitCompareStrictS(LCompareStrictS *lir)
 {
     JSOp op = lir->mir()->jsop();
     JS_ASSERT(op == JSOP_STRICTEQ || op == JSOP_STRICTNE);
 
     const ValueOperand leftV = ToValue(lir, LCompareStrictS::Lhs);
     Register right = ToRegister(lir->right());
     Register output = ToRegister(lir->output());
-    Register temp = ToRegister(lir->temp0());
+    Register temp = ToRegister(lir->temp());
+    Register tempToUnbox = ToTempUnboxRegister(lir->tempToUnbox());
 
     Label string, done;
 
     masm.branchTestString(Assembler::Equal, leftV, &string);
     masm.move32(Imm32(op == JSOP_STRICTNE), output);
     masm.jump(&done);
 
     masm.bind(&string);
-    Register left = masm.extractString(leftV, ToRegister(lir->temp1()));
+    Register left = masm.extractString(leftV, tempToUnbox);
     if (!emitCompareS(lir, op, left, right, output, temp))
         return false;
 
     masm.bind(&done);
 
     return true;
 }
 
@@ -3705,19 +3706,19 @@ CodeGenerator::visitIsNullOrLikeUndefine
         masm.branchTestNull(Assembler::Equal, tag, nullOrLikeUndefined);
         masm.branchTestUndefined(Assembler::Equal, tag, nullOrLikeUndefined);
 
         if (ool) {
             // Check whether it's a truthy object or a falsy object that emulates
             // undefined.
             masm.branchTestObject(Assembler::NotEqual, tag, notNullOrLikeUndefined);
 
-            Register objreg = masm.extractObject(value, ToRegister(lir->temp0()));
+            Register objreg = masm.extractObject(value, ToTempUnboxRegister(lir->tempToUnbox()));
             testObjectTruthy(objreg, notNullOrLikeUndefined, nullOrLikeUndefined,
-                             ToRegister(lir->temp1()), ool);
+                             ToRegister(lir->temp()), ool);
         }
 
         Label done;
 
         // It's not null or undefined, and if it's an object it doesn't
         // emulate undefined, so it's not like undefined.
         masm.bind(notNullOrLikeUndefined);
         masm.move32(Imm32(op == JSOP_NE), output);
@@ -3784,18 +3785,18 @@ CodeGenerator::visitIsNullOrLikeUndefine
 
         masm.branchTestNull(Assembler::Equal, tag, ifTrueLabel);
         masm.branchTestUndefined(Assembler::Equal, tag, ifTrueLabel);
 
         if (ool) {
             masm.branchTestObject(Assembler::NotEqual, tag, ifFalseLabel);
 
             // Objects that emulate undefined are loosely equal to null/undefined.
-            Register objreg = masm.extractObject(value, ToRegister(lir->temp0()));
-            testObjectTruthy(objreg, ifFalseLabel, ifTrueLabel, ToRegister(lir->temp1()), ool);
+            Register objreg = masm.extractObject(value, ToTempUnboxRegister(lir->tempToUnbox()));
+            testObjectTruthy(objreg, ifFalseLabel, ifTrueLabel, ToRegister(lir->temp()), ool);
         } else {
             masm.jump(ifFalseLabel);
         }
         return true;
     }
 
     JS_ASSERT(op == JSOP_STRICTEQ || op == JSOP_STRICTNE);
 
--- a/js/src/ion/IonMacroAssembler.cpp
+++ b/js/src/ion/IonMacroAssembler.cpp
@@ -78,16 +78,17 @@ MacroAssembler::guardTypeSet(const Sourc
     if (types->hasType(types::Type::NullType()))
         branchTestNull(Equal, tag, matched);
     if (types->hasType(types::Type::MagicArgType()))
         branchTestMagic(Equal, tag, matched);
 
     if (types->hasType(types::Type::AnyObjectType())) {
         branchTestObject(Equal, tag, matched);
     } else if (types->getObjectCount()) {
+        JS_ASSERT(scratch != InvalidReg);
         branchTestObject(NotEqual, tag, miss);
         Register obj = extractObject(address, scratch);
 
         unsigned count = types->getObjectCount();
         for (unsigned i = 0; i < count; i++) {
             if (JSObject *object = types->getSingleObject(i))
                 branchPtr(Equal, obj, ImmGCPtr(object), matched);
         }
--- a/js/src/ion/LIR-Common.h
+++ b/js/src/ion/LIR-Common.h
@@ -1556,20 +1556,20 @@ class LCompareStrictS : public LInstruct
         setTemp(1, temp1);
     }
 
     static const size_t Lhs = 0;
 
     const LAllocation *right() {
         return getOperand(BOX_PIECES);
     }
-    const LDefinition *temp0() {
+    const LDefinition *temp() {
         return getTemp(0);
     }
-    const LDefinition *temp1() {
+    const LDefinition *tempToUnbox() {
         return getTemp(1);
     }
     MCompare *mir() {
         return mir_->toCompare();
     }
 };
 
 // Used for strict-equality comparisons where one side is a boolean
@@ -1675,65 +1675,65 @@ class LCompareVM : public LCallInstructi
     }
 };
 
 class LIsNullOrLikeUndefined : public LInstructionHelper<1, BOX_PIECES, 2>
 {
   public:
     LIR_HEADER(IsNullOrLikeUndefined)
 
-    LIsNullOrLikeUndefined(const LDefinition &temp0, const LDefinition &temp1)
+    LIsNullOrLikeUndefined(const LDefinition &temp, const LDefinition &tempToUnbox)
     {
-        setTemp(0, temp0);
-        setTemp(1, temp1);
+        setTemp(0, temp);
+        setTemp(1, tempToUnbox);
     }
 
     static const size_t Value = 0;
 
     MCompare *mir() {
         return mir_->toCompare();
     }
 
-    const LDefinition *temp0() {
+    const LDefinition *temp() {
         return getTemp(0);
     }
 
-    const LDefinition *temp1() {
+    const LDefinition *tempToUnbox() {
         return getTemp(1);
     }
 };
 
 class LIsNullOrLikeUndefinedAndBranch : public LControlInstructionHelper<2, BOX_PIECES, 2>
 {
   public:
     LIR_HEADER(IsNullOrLikeUndefinedAndBranch)
 
-    LIsNullOrLikeUndefinedAndBranch(MBasicBlock *ifTrue, MBasicBlock *ifFalse, const LDefinition &temp0, const LDefinition &temp1)
+    LIsNullOrLikeUndefinedAndBranch(MBasicBlock *ifTrue, MBasicBlock *ifFalse, const LDefinition &temp, const LDefinition &tempToUnbox)
     {
         setSuccessor(0, ifTrue);
         setSuccessor(1, ifFalse);
-        setTemp(0, temp0);
-        setTemp(1, temp1);
+        setTemp(0, temp);
+        setTemp(1, tempToUnbox);
     }
 
     static const size_t Value = 0;
 
     MBasicBlock *ifTrue() const {
         return getSuccessor(0);
     }
     MBasicBlock *ifFalse() const {
         return getSuccessor(1);
     }
     MCompare *mir() {
         return mir_->toCompare();
     }
-    const LDefinition *temp0() {
+    const LDefinition *temp() {
         return getTemp(0);
     }
-    const LDefinition *temp1() {
+    const LDefinition *tempToUnbox() {
         return getTemp(1);
     }
 };
 
 // Takes an object and tests whether it emulates |undefined|, as determined by
 // the JSCLASS_EMULATES_UNDEFINED class flag on unwrapped objects.  See also
 // js::EmulatesUndefined.
 class LEmulatesUndefined : public LInstructionHelper<1, 1, 0>
--- a/js/src/ion/Lowering.cpp
+++ b/js/src/ion/Lowering.cpp
@@ -601,27 +601,27 @@ LIRGenerator::visitTest(MTest *test)
                 MOZ_ASSERT(comp->operandMightEmulateUndefined(),
                            "MCompare::tryFold should handle the never-emulates-undefined case");
 
                 LEmulatesUndefinedAndBranch *lir =
                     new LEmulatesUndefinedAndBranch(useRegister(left), ifTrue, ifFalse, temp());
                 return add(lir, comp);
             }
 
-            LDefinition temp0, temp1;
+            LDefinition tmp, tmpToUnbox;
             if (comp->operandMightEmulateUndefined()) {
-                temp0 = temp();
-                temp1 = temp();
+                tmp = temp();
+                tmpToUnbox = tempToUnbox();
             } else {
-                temp0 = LDefinition::BogusTemp();
-                temp1 = LDefinition::BogusTemp();
+                tmp = LDefinition::BogusTemp();
+                tmpToUnbox = LDefinition::BogusTemp();
             }
 
             LIsNullOrLikeUndefinedAndBranch *lir =
-                new LIsNullOrLikeUndefinedAndBranch(ifTrue, ifFalse, temp0, temp1);
+                new LIsNullOrLikeUndefinedAndBranch(ifTrue, ifFalse, tmp, tmpToUnbox);
             if (!useBox(lir, LIsNullOrLikeUndefinedAndBranch::Value, left))
                 return false;
             return add(lir, comp);
         }
 
         // Compare and branch booleans.
         if (comp->compareType() == MCompare::Compare_Boolean) {
             JS_ASSERT(left->type() == MIRType_Value);
@@ -744,17 +744,17 @@ LIRGenerator::visitCompare(MCompare *com
         return assignSafepoint(lir, comp);
     }
 
     // Strict compare between value and string
     if (comp->compareType() == MCompare::Compare_StrictString) {
         JS_ASSERT(left->type() == MIRType_Value);
         JS_ASSERT(right->type() == MIRType_String);
 
-        LCompareStrictS *lir = new LCompareStrictS(useRegister(right), temp(), temp());
+        LCompareStrictS *lir = new LCompareStrictS(useRegister(right), temp(), tempToUnbox());
         if (!useBox(lir, LCompareStrictS::Lhs, left))
             return false;
         if (!define(lir, comp))
             return false;
         return assignSafepoint(lir, comp);
     }
 
     // Unknown/unspecialized compare use a VM call.
@@ -780,26 +780,26 @@ LIRGenerator::visitCompare(MCompare *com
     {
         if (left->type() == MIRType_Object) {
             MOZ_ASSERT(comp->operandMightEmulateUndefined(),
                        "MCompare::tryFold should have folded this away");
 
             return define(new LEmulatesUndefined(useRegister(left)), comp);
         }
 
-        LDefinition temp0, temp1;
+        LDefinition tmp, tmpToUnbox;
         if (comp->operandMightEmulateUndefined()) {
-            temp0 = temp();
-            temp1 = temp();
+            tmp = temp();
+            tmpToUnbox = tempToUnbox();
         } else {
-            temp0 = LDefinition::BogusTemp();
-            temp1 = LDefinition::BogusTemp();
+            tmp = LDefinition::BogusTemp();
+            tmpToUnbox = LDefinition::BogusTemp();
         }
 
-        LIsNullOrLikeUndefined *lir = new LIsNullOrLikeUndefined(temp0, temp1);
+        LIsNullOrLikeUndefined *lir = new LIsNullOrLikeUndefined(tmp, tmpToUnbox);
         if (!useBox(lir, LIsNullOrLikeUndefined::Value, left))
             return false;
         return define(lir, comp);
     }
 
     // Compare booleans.
     if (comp->compareType() == MCompare::Compare_Boolean) {
         JS_ASSERT(left->type() == MIRType_Value);
@@ -1727,30 +1727,40 @@ LIRGenerator::visitStoreSlot(MStoreSlot 
     return true;
 }
 
 bool
 LIRGenerator::visitTypeBarrier(MTypeBarrier *ins)
 {
     // Requesting a non-GC pointer is safe here since we never re-enter C++
     // from inside a type barrier test.
-    LTypeBarrier *barrier = new LTypeBarrier(temp());
+
+    const types::StackTypeSet *types = ins->resultTypeSet();
+    bool needTemp = !types->unknownObject() && types->getObjectCount() > 0;
+    LDefinition tmp = needTemp ? temp() : tempToUnbox();
+
+    LTypeBarrier *barrier = new LTypeBarrier(tmp);
     if (!useBox(barrier, LTypeBarrier::Input, ins->input()))
         return false;
     if (!assignSnapshot(barrier, ins->bailoutKind()))
         return false;
     return redefine(ins, ins->input()) && add(barrier, ins);
 }
 
 bool
 LIRGenerator::visitMonitorTypes(MMonitorTypes *ins)
 {
     // Requesting a non-GC pointer is safe here since we never re-enter C++
     // from inside a type check.
-    LMonitorTypes *lir = new LMonitorTypes(temp());
+
+    const types::StackTypeSet *types = ins->typeSet();
+    bool needTemp = !types->unknownObject() && types->getObjectCount() > 0;
+    LDefinition tmp = needTemp ? temp() : tempToUnbox();
+
+    LMonitorTypes *lir = new LMonitorTypes(tmp);
     if (!useBox(lir, LMonitorTypes::Input, ins->input()))
         return false;
     return assignSnapshot(lir, Bailout_Normal) && add(lir, ins);
 }
 
 bool
 LIRGenerator::visitPostWriteBarrier(MPostWriteBarrier *ins)
 {
@@ -1758,17 +1768,17 @@ LIRGenerator::visitPostWriteBarrier(MPos
     switch (ins->value()->type()) {
       case MIRType_Object: {
         LPostWriteBarrierO *lir = new LPostWriteBarrierO(useRegisterOrConstant(ins->object()),
                                                          useRegister(ins->value()));
         return add(lir, ins) && assignSafepoint(lir, ins);
       }
       case MIRType_Value: {
         LPostWriteBarrierV *lir =
-            new LPostWriteBarrierV(useRegisterOrConstant(ins->object()), temp());
+            new LPostWriteBarrierV(useRegisterOrConstant(ins->object()), tempToUnbox());
         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/ion/arm/Lowering-arm.h
+++ b/js/src/ion/arm/Lowering-arm.h
@@ -21,16 +21,20 @@ class LIRGeneratorARM : public LIRGenera
 
   protected:
     // Adds a box input to an instruction, setting operand |n| to the type and
     // |n+1| to the payload.
     bool useBox(LInstruction *lir, size_t n, MDefinition *mir,
                 LUse::Policy policy = LUse::REGISTER, bool useAtStart = false);
     bool useBoxFixed(LInstruction *lir, size_t n, MDefinition *mir, Register reg1, Register reg2);
 
+    inline LDefinition tempToUnbox() {
+        return LDefinition::BogusTemp();
+    }
+
     void lowerUntypedPhiInput(MPhi *phi, uint32_t inputPosition, LBlock *block, size_t lirIndex);
     bool defineUntypedPhi(MPhi *phi, size_t lirIndex);
     bool lowerForShift(LInstructionHelper<1, 2, 0> *ins, MDefinition *mir, MDefinition *lhs,
                        MDefinition *rhs);
     bool lowerUrshD(MUrsh *mir);
 
     bool lowerForALU(LInstructionHelper<1, 1, 0> *ins, MDefinition *mir,
                      MDefinition *input);
--- a/js/src/ion/shared/CodeGenerator-shared-inl.h
+++ b/js/src/ion/shared/CodeGenerator-shared-inl.h
@@ -41,16 +41,24 @@ ToRegister(const LAllocation *a)
 
 static inline Register
 ToRegister(const LDefinition *def)
 {
     return ToRegister(*def->output());
 }
 
 static inline Register
+ToTempUnboxRegister(const LDefinition *def)
+{
+    if (def->isBogusTemp())
+        return InvalidReg;
+    return ToRegister(def);
+}
+
+static inline Register
 ToRegisterOrInvalid(const LAllocation *a)
 {
     return a ? ToRegister(*a) : InvalidReg;
 }
 
 static inline FloatRegister
 ToFloatRegister(const LAllocation &a)
 {
--- a/js/src/ion/x64/Lowering-x64.h
+++ b/js/src/ion/x64/Lowering-x64.h
@@ -23,16 +23,20 @@ class LIRGeneratorX64 : public LIRGenera
     void lowerUntypedPhiInput(MPhi *phi, uint32_t inputPosition, LBlock *block, size_t lirIndex);
     bool defineUntypedPhi(MPhi *phi, size_t lirIndex);
 
     // Adds a use at operand |n| of a value-typed insturction.
     bool useBox(LInstruction *lir, size_t n, MDefinition *mir,
                 LUse::Policy policy = LUse::REGISTER, bool useAtStart = false);
     bool useBoxFixed(LInstruction *lir, size_t n, MDefinition *mir, Register reg1, Register);
 
+    inline LDefinition tempToUnbox() {
+        return temp();
+    }
+
     LGetPropertyCacheT *newLGetPropertyCacheT(MGetPropertyCache *ins);
 
   public:
     bool visitBox(MBox *box);
     bool visitUnbox(MUnbox *unbox);
     bool visitReturn(MReturn *ret);
     bool visitStoreTypedArrayElement(MStoreTypedArrayElement *ins);
     bool visitStoreTypedArrayElementHole(MStoreTypedArrayElementHole *ins);
--- a/js/src/ion/x86/Lowering-x86.h
+++ b/js/src/ion/x86/Lowering-x86.h
@@ -21,16 +21,20 @@ class LIRGeneratorX86 : public LIRGenera
 
   protected:
     // Adds a box input to an instruction, setting operand |n| to the type and
     // |n+1| to the payload.
     bool useBox(LInstruction *lir, size_t n, MDefinition *mir,
                 LUse::Policy policy = LUse::REGISTER, bool useAtStart = false);
     bool useBoxFixed(LInstruction *lir, size_t n, MDefinition *mir, Register reg1, Register reg2);
 
+    inline LDefinition tempToUnbox() {
+        return LDefinition::BogusTemp();
+    }
+
     void lowerUntypedPhiInput(MPhi *phi, uint32_t inputPosition, LBlock *block, size_t lirIndex);
     bool defineUntypedPhi(MPhi *phi, size_t lirIndex);
 
     LGetPropertyCacheT *newLGetPropertyCacheT(MGetPropertyCache *ins);
 
   public:
     bool visitBox(MBox *box);
     bool visitUnbox(MUnbox *unbox);