Bug 885169 - Spidermonkey: Alleviate register allocation constraints in ICGetElem_Arguments::Compiler::generateStubCode. r=nbp
authorDan Gohman <sunfish@google.com>
Wed, 04 Sep 2013 21:16:07 -0700
changeset 146065 e2be9740720f87ecb46d0abcc1dc5219b78ab9c7
parent 146064 26006e5cefdcd37bc68aa4ad4aaa55fe68d8abb6
child 146066 0d651ed131b355f653453597b9b5addfa7147cd6
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersnbp
bugs885169
milestone26.0a1
Bug 885169 - Spidermonkey: Alleviate register allocation constraints in ICGetElem_Arguments::Compiler::generateStubCode. r=nbp
js/src/jit/BaselineIC.cpp
js/src/jit/arm/MacroAssembler-arm.h
js/src/jit/x86/MacroAssembler-x86.h
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -4461,17 +4461,17 @@ ICGetElem_Arguments::Compiler::generateS
 
     // Length check succeeded, now check the correct bit.  We clobber potential type regs
     // now.  Inputs will have to be reconstructed if we fail after this point, but that's
     // unlikely.
     Label failureReconstructInputs;
     regs = availableGeneralRegs(0);
     regs.takeUnchecked(objReg);
     regs.takeUnchecked(idxReg);
-    regs.takeUnchecked(scratchReg);
+    regs.take(scratchReg);
     Register argData = regs.takeAny();
     Register tempReg = regs.takeAny();
 
     // Load ArgumentsData
     masm.loadPrivate(Address(objReg, ArgumentsObject::getDataSlotOffset()), argData);
 
     // Load deletedBits bitArray pointer into scratchReg
     masm.loadPtr(Address(argData, offsetof(ArgumentsData, deletedBits)), scratchReg);
@@ -4483,16 +4483,17 @@ ICGetElem_Arguments::Compiler::generateS
 
     // Don't bother testing specific bit, if any bit is set in the word, fail.
     masm.branchPtr(Assembler::NotEqual, scratchReg, ImmWord((size_t)0), &failureReconstructInputs);
 
     // Load the value.  use scratchReg and tempReg to form a ValueOperand to load into.
     masm.addPtr(Imm32(ArgumentsData::offsetOfArgs()), argData);
     regs.add(scratchReg);
     regs.add(tempReg);
+    regs.add(argData);
     ValueOperand tempVal = regs.takeAnyValue();
     masm.loadValue(BaseIndex(argData, idxReg, ScaleFromElemWidth(sizeof(Value))), tempVal);
 
     // Makesure that this is not a FORWARD_TO_CALL_SLOT magic value.
     masm.branchTestMagic(Assembler::Equal, tempVal, &failureReconstructInputs);
 
     // Everything checked out, return value.
     masm.moveValue(tempVal, R0);
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -949,22 +949,40 @@ class MacroAssemblerARMCompat : public M
             loadInt32OrDouble(address.base, address.index, dest.fpu(), address.scale);
         else
             load32(address, dest.gpr());
     }
 
     void moveValue(const Value &val, const ValueOperand &dest);
 
     void moveValue(const ValueOperand &src, const ValueOperand &dest) {
-        JS_ASSERT(src.typeReg() != dest.payloadReg());
-        JS_ASSERT(src.payloadReg() != dest.typeReg());
-        if (src.typeReg() != dest.typeReg())
-            ma_mov(src.typeReg(), dest.typeReg());
-        if (src.payloadReg() != dest.payloadReg())
-            ma_mov(src.payloadReg(), dest.payloadReg());
+        Register s0 = src.typeReg(), d0 = dest.typeReg(),
+                 s1 = src.payloadReg(), d1 = dest.payloadReg();
+
+        // Either one or both of the source registers could be the same as a
+        // destination register.
+        if (s1 == d0) {
+            if (s0 == d1) {
+                // If both are, this is just a swap of two registers.
+                JS_ASSERT(d1 != ScratchRegister);
+                JS_ASSERT(d0 != ScratchRegister);
+                ma_mov(d1, ScratchRegister);
+                ma_mov(d0, d1);
+                ma_mov(ScratchRegister, d0);
+                return;
+            }
+            // If only one is, copy that source first.
+            mozilla::Swap(s0, s1);
+            mozilla::Swap(d0, d1);
+        }
+
+        if (s0 != d0)
+            ma_mov(s0, d0);
+        if (s1 != d1)
+            ma_mov(s1, d1);
     }
 
     void storeValue(ValueOperand val, Operand dst);
     void storeValue(ValueOperand val, const BaseIndex &dest);
     void storeValue(JSValueType type, Register reg, BaseIndex dest) {
         // Harder cases not handled yet.
         JS_ASSERT(dest.offset == 0);
         ma_alu(dest.base, lsl(dest.index, dest.scale), ScratchRegister, op_add);
--- a/js/src/jit/x86/MacroAssembler-x86.h
+++ b/js/src/jit/x86/MacroAssembler-x86.h
@@ -108,22 +108,36 @@ class MacroAssemblerX86 : public MacroAs
             movl(ImmGCPtr(reinterpret_cast<gc::Cell *>(val.toGCThing())), data);
         else
             movl(Imm32(jv.s.payload.i32), data);
     }
     void moveValue(const Value &val, const ValueOperand &dest) {
         moveValue(val, dest.typeReg(), dest.payloadReg());
     }
     void moveValue(const ValueOperand &src, const ValueOperand &dest) {
-        JS_ASSERT(src.typeReg() != dest.payloadReg());
-        JS_ASSERT(src.payloadReg() != dest.typeReg());
-        if (src.typeReg() != dest.typeReg())
-            movl(src.typeReg(), dest.typeReg());
-        if (src.payloadReg() != dest.payloadReg())
-            movl(src.payloadReg(), dest.payloadReg());
+        Register s0 = src.typeReg(), d0 = dest.typeReg(),
+                 s1 = src.payloadReg(), d1 = dest.payloadReg();
+
+        // Either one or both of the source registers could be the same as a
+        // destination register.
+        if (s1 == d0) {
+            if (s0 == d1) {
+                // If both are, this is just a swap of two registers.
+                xchgl(d0, d1);
+                return;
+            }
+            // If only one is, copy that source first.
+            mozilla::Swap(s0, s1);
+            mozilla::Swap(d0, d1);
+        }
+
+        if (s0 != d0)
+            movl(s0, d0);
+        if (s1 != d1)
+            movl(s1, d1);
     }
 
     /////////////////////////////////////////////////////////////////
     // X86/X64-common interface.
     /////////////////////////////////////////////////////////////////
     void storeValue(ValueOperand val, Operand dest) {
         movl(val.payloadReg(), ToPayload(dest));
         movl(val.typeReg(), ToType(dest));