[INFER] Don't clobber address register in FrameState::storeTo, bug 649689. r=bhackett
authorJan de Mooij <jandemooij@gmail.com>
Wed, 13 Apr 2011 12:38:23 -0700
changeset 74939 a3eeee8f7803279669dbba47f6c5e57ea9995942
parent 74938 ff1ae67e49860b6cf3348a9d31bec51965d71eef
child 74940 affaa35f4a14cc23844d2d062099c9daa11f6364
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
reviewersbhackett
bugs649689
milestone6.0a1
[INFER] Don't clobber address register in FrameState::storeTo, bug 649689. r=bhackett
js/src/jit-test/tests/jaeger/bug649689.js
js/src/methodjit/FrameState.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/bug649689.js
@@ -0,0 +1,6 @@
+function f(x) {
+    eval("a = 3");
+    x.p = x.p = a;
+    assertEq(x.p, 3);
+}
+f({p: 2});
--- a/js/src/methodjit/FrameState.cpp
+++ b/js/src/methodjit/FrameState.cpp
@@ -1086,17 +1086,16 @@ FrameState::storeTo(FrameEntry *fe, Addr
     if (fe->isConstant()) {
         masm.storeValue(fe->getValue(), address);
         return;
     }
 
     if (fe->isCopy())
         fe = fe->copyOf();
 
-    /* Cannot clobber the address's register. */
     JS_ASSERT(!a->freeRegs.hasReg(address.base));
 
     /* If loading from memory, ensure destination differs. */
     JS_ASSERT_IF((fe->type.inMemory() || fe->data.inMemory()),
                  addressOf(fe).base != address.base ||
                  addressOf(fe).offset != address.offset);
 
     if (fe->data.inFPRegister()) {
@@ -1106,22 +1105,29 @@ FrameState::storeTo(FrameEntry *fe, Addr
 
     if (fe->isType(JSVAL_TYPE_DOUBLE)) {
         JS_ASSERT(fe->data.inMemory());
         masm.loadDouble(addressOf(fe), Registers::FPConversionTemp);
         masm.storeDouble(Registers::FPConversionTemp, address);
         return;
     }
 
+    /* Don't clobber the address's register. */
+    bool pinAddressReg = !!regstate(address.base).fe();
+    if (pinAddressReg)
+        pinReg(address.base);
+
 #if defined JS_PUNBOX64
     if (fe->type.inMemory() && fe->data.inMemory()) {
         /* Future optimization: track that the Value is in a register. */
         RegisterID vreg = Registers::ValueReg;
         masm.loadPtr(addressOf(fe), vreg);
         masm.storePtr(vreg, address);
+        if (pinAddressReg)
+            unpinReg(address.base);
         return;
     }
 
     JS_ASSERT(!fe->isType(JSVAL_TYPE_DOUBLE));
 
     /*
      * If dreg is obtained via allocReg(), then calling
      * pinReg() trips an assertion. But in all other cases,
@@ -1214,16 +1220,18 @@ FrameState::storeTo(FrameEntry *fe, Addr
         }
         masm.storeTypeTag(reg, address);
         if (popped)
             freeReg(reg);
         else
             fe->type.setRegister(reg);
     }
 #endif
+    if (pinAddressReg)
+        unpinReg(address.base);
 }
 
 void
 FrameState::loadThisForReturn(RegisterID typeReg, RegisterID dataReg, RegisterID tempReg)
 {
     return loadForReturn(getThis(), typeReg, dataReg, tempReg);
 }