[INFER] Fix ensureInteger to forget allocated GP register, bug 655505. r=bhackett
authorJan de Mooij <jandemooij@gmail.com>
Sat, 07 May 2011 20:40:44 +0200
changeset 75002 325744fbf7f00567027fdc3af4b8a9a4f5d161e5
parent 75001 e09e209d988edf62e39bab04fd2a590b425b2c5b
child 75005 24a2e5740ab8b1a018af6bee5fbc734bc5955f1a
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
reviewersbhackett
bugs655505
milestone6.0a1
[INFER] Fix ensureInteger to forget allocated GP register, bug 655505. r=bhackett
js/src/jit-test/tests/jaeger/bug655505.js
js/src/methodjit/Compiler.cpp
js/src/methodjit/FrameState-inl.h
js/src/methodjit/FrameState.cpp
js/src/methodjit/FrameState.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/bug655505.js
@@ -0,0 +1,12 @@
+var a = [, , , , , , ];
+exhaustiveSliceTest("exhaustive slice test 1", a);
+function mySlice(a, from, to) {
+    var to2 = to;
+    if (to2 < 0) {
+        to2 = to2.length + to;
+    }
+}
+function exhaustiveSliceTest(testname, a) { x = a; }
+for (y = a.length; y >= 0; y--) {
+    mySlice(a, x, y);
+}
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -1372,17 +1372,17 @@ mjit::Compiler::generateMethod()
             restoreAnalysisTypes();
             fallthrough = true;
 
             if (!cx->typeInferenceEnabled()) {
                 /* All join points have synced state if we aren't doing cross-branch regalloc. */
                 opinfo->safePoint = true;
             }
         }
-
+        frame.assertValidRegisterState();
         a->jumpMap[uint32(PC - script->code)] = masm.label();
 
         SPEW_OPCODE();
         JS_ASSERT(frame.stackDepth() == opinfo->stackDepth);
 
         if (trap) {
             REJOIN_SITE(CallSite::MAGIC_TRAP_ID);
             prepareStubCall(Uses(0));
@@ -2834,19 +2834,17 @@ mjit::Compiler::generateMethod()
                 FrameEntry *fe = frame.getStack(opinfo->stackDepth - nuses + i);
                 if (fe) {
                     /* fe may be NULL for conditionally pushed entries, e.g. JSOP_AND */
                     frame.extra(fe).types = analysis->pushedTypes(oldPC - script->code, i);
                 }
             }
         }
 
-#ifdef DEBUG
         frame.assertValidRegisterState();
-#endif
     }
 
   done:
     return Compile_Okay;
 }
 
 #undef END_CASE
 #undef BEGIN_CASE
--- a/js/src/methodjit/FrameState-inl.h
+++ b/js/src/methodjit/FrameState-inl.h
@@ -558,16 +558,18 @@ inline JSC::MacroAssembler::FPRegisterID
 FrameState::tempFPRegForData(FrameEntry *fe)
 {
     JS_ASSERT(!fe->isConstant());
     JS_ASSERT(fe->isType(JSVAL_TYPE_DOUBLE));
 
     if (fe->isCopy())
         fe = fe->copyOf();
 
+    JS_ASSERT(!fe->data.inRegister());
+
     if (fe->data.inFPRegister())
         return fe->data.fpreg();
 
     FPRegisterID reg = allocAndLoadReg(fe, true, RematInfo::DATA).fpreg();
     fe->data.setFPRegister(reg);
     return reg;
 }
 
@@ -617,16 +619,18 @@ FrameState::tempRegInMaskForData(FrameEn
 inline JSC::MacroAssembler::RegisterID
 FrameState::tempRegForData(FrameEntry *fe, RegisterID reg, Assembler &masm) const
 {
     JS_ASSERT(!fe->data.isConstant());
 
     if (fe->isCopy())
         fe = fe->copyOf();
 
+    JS_ASSERT(!fe->data.inFPRegister());
+
     if (fe->data.inRegister()) {
         JS_ASSERT(fe->data.reg() != reg);
         return fe->data.reg();
     } else {
         masm.loadPayload(addressOf(fe), reg);
         return reg;
     }
 }
@@ -901,29 +905,35 @@ FrameState::forgetType(FrameEntry *fe)
     fe->type.setMemory();
 }
 
 inline void
 FrameState::learnType(FrameEntry *fe, JSValueType type, bool unsync)
 {
     JS_ASSERT(!fe->isType(JSVAL_TYPE_DOUBLE));
     JS_ASSERT(type != JSVAL_TYPE_UNKNOWN);
+
+    if (type == JSVAL_TYPE_DOUBLE)
+        JS_ASSERT(!fe->data.inRegister());
+    else
+        JS_ASSERT(!fe->data.inFPRegister());
+
     if (fe->type.inRegister())
         forgetReg(fe->type.reg());
     fe->setType(type);
     if (unsync)
         fe->type.unsync();
 }
 
 inline void
 FrameState::learnType(FrameEntry *fe, JSValueType type, RegisterID data)
 {
     /* The copied bit may be set on an entry, but there should not be any actual copies. */
     JS_ASSERT_IF(fe->isCopied(), !isEntryCopied(fe));
-    JS_ASSERT(type != JSVAL_TYPE_UNKNOWN);
+    JS_ASSERT(type != JSVAL_TYPE_UNKNOWN && type != JSVAL_TYPE_DOUBLE);
 
     forgetAllRegs(fe);
     fe->clear();
 
     fe->type.setConstant();
     fe->knownType = type;
 
     fe->data.setRegister(data);
--- a/js/src/methodjit/FrameState.cpp
+++ b/js/src/methodjit/FrameState.cpp
@@ -2085,18 +2085,28 @@ FrameState::ensureInteger(FrameEntry *fe
     if (fe->isConstant()) {
         Value newValue = Int32Value(int32(fe->getValue().toDouble()));
         fe->setConstant(Jsvalify(newValue));
         return;
     }
 
     JS_ASSERT(!fe->isCopy() && !fe->isCopied());
 
-    if (!fe->isType(JSVAL_TYPE_DOUBLE))
+    if (!fe->isType(JSVAL_TYPE_DOUBLE)) {
+        /*
+         * A normal register may have been allocated after calling
+         * syncAndForgetEverything.
+         */
+        if (fe->data.inRegister()) {
+            syncFe(fe);
+            forgetReg(fe->data.reg());
+            fe->data.setMemory();
+        }
         learnType(fe, JSVAL_TYPE_DOUBLE, false);
+    }
 
     RegisterID reg = allocReg();
     FPRegisterID fpreg = tempFPRegForData(fe);
     Jump j = masm.branchTruncateDoubleToInt32(fpreg, reg);
     j.linkTo(masm.label(), &masm);
 
     forgetAllRegs(fe);
     fe->resetUnsynced();
--- a/js/src/methodjit/FrameState.h
+++ b/js/src/methodjit/FrameState.h
@@ -820,16 +820,18 @@ class FrameState
     //   2 for callee, this +
     //   nargs +
     //   nfixed +
     //   currently pushed stack slots
     uint32 frameSlots() const { return uint32(sp - entries); }
 
 #ifdef DEBUG
     void assertValidRegisterState() const;
+#else
+    inline void assertValidRegisterState() const {};
 #endif
 
     // Return an address, relative to the StackFrame, that represents where
     // this FrameEntry is stored in memory. Note that this is its canonical
     // address, not its backing store. There is no guarantee that the memory
     // is coherent.
     Address addressOf(const FrameEntry *fe) const { return addressOf(fe, a); }
     Address addressOf(uint32 slot) const { return addressOf(entries + slot); }