[JAEGER] Keep track of which operations result in numbers.
authorDavid Anderson <danderson@mozilla.com>
Thu, 22 Jul 2010 17:34:29 -0700
changeset 53153 87e07ff8196caff03a2d480da82645d944d0f283
parent 53152 51ed7672df50fbc43858f1235b448160425111f6
child 53154 a71ac4cc1d1726a4226eebe43f1ec53fb3e38e6f
push id15660
push userrsayre@mozilla.com
push dateSat, 11 Sep 2010 19:16:24 +0000
treeherdermozilla-central@f1bd314e64ac [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone2.0b2pre
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
[JAEGER] Keep track of which operations result in numbers.
js/src/methodjit/FrameEntry.h
js/src/methodjit/FrameState-inl.h
js/src/methodjit/FrameState.cpp
js/src/methodjit/FrameState.h
js/src/methodjit/nunbox/FastArithmetic.cpp
--- a/js/src/methodjit/FrameEntry.h
+++ b/js/src/methodjit/FrameEntry.h
@@ -91,31 +91,37 @@ class FrameEntry
         return isTypeKnown() && getKnownType() != type_;
     }
 
     uint32 getPayload32() const {
         //JS_ASSERT(!Valueify(v_.asBits).isDouble() || type.synced());
         return v_.s.payload.u32;
     }
 
+    bool isCachedNumber() const {
+        return isNumber;
+    }
+
   private:
     void setType(JSValueType type_) {
         type.setConstant();
         v_.s.tag = JSVAL_TYPE_TO_TAG(type_);
         knownType = type_;
+        JS_ASSERT(!isNumber);
     }
 
     void track(uint32 index) {
         clear();
         index_ = index;
     }
 
     void clear() {
         copied = false;
         copy = NULL;
+        isNumber = false;
     }
 
     uint32 trackerIndex() {
         return index_;
     }
 
     /*
      * Marks the FE as unsynced & invalid.
@@ -190,16 +196,17 @@ class FrameEntry
   private:
     JSValueType knownType;
     jsval_layout v_;
     RematInfo  type;
     RematInfo  data;
     uint32     index_;
     FrameEntry *copy;
     bool       copied;
-    char       padding[3];
+    bool       isNumber;
+    char       padding[2];
 };
 
 } /* namespace mjit */
 } /* namespace js */
 
 #endif /* jsjaeger_valueinfo_h__ */
 
--- a/js/src/methodjit/FrameState-inl.h
+++ b/js/src/methodjit/FrameState-inl.h
@@ -292,16 +292,38 @@ FrameState::pushTypedPayload(JSValueType
 
     fe->resetUnsynced();
     fe->setType(type);
     fe->data.setRegister(payload);
     regstate[payload] = RegisterState(fe, RematInfo::DATA);
 }
 
 inline void
+FrameState::pushNumber(MaybeRegisterID payload)
+{
+    JS_ASSERT_IF(payload.isSet(), !freeRegs.hasReg(payload.reg()));
+
+    FrameEntry *fe = rawPush();
+    fe->clear();
+
+    JS_ASSERT(!fe->isNumber);
+
+    fe->type.setMemory();
+    fe->isNumber = true;
+
+    if (payload.isSet()) {
+        fe->data.unsync();
+        fe->data.setRegister(payload.reg());
+        regstate[payload.reg()] = RegisterState(fe, RematInfo::DATA);
+    } else {
+        fe->data.setMemory();
+    }
+}
+
+inline void
 FrameState::pushUntypedPayload(JSValueType type, RegisterID payload,
                                bool popGuaranteed, bool fastType)
 {
     JS_ASSERT(!freeRegs.hasReg(payload));
 
     FrameEntry *fe = rawPush();
 
     fe->clear();
@@ -473,16 +495,19 @@ FrameState::forgetType(FrameEntry *fe)
     fe->type.setMemory();
 }
 
 inline void
 FrameState::learnType(FrameEntry *fe, JSValueType type)
 {
     if (fe->type.inRegister())
         forgetReg(fe->type.reg());
+#ifdef DEBUG
+    fe->isNumber = false;
+#endif
     fe->setType(type);
 }
 
 inline JSC::MacroAssembler::Address
 FrameState::addressOf(const FrameEntry *fe) const
 {
     uint32 index = (fe - entries);
     JS_ASSERT(index >= nargs);
@@ -722,30 +747,30 @@ FrameState::giveOwnRegs(FrameEntry *fe)
         pop();
         pushRegs(type, data);
     }
 }
 
 inline void
 FrameState::loadDouble(FrameEntry *fe, FPRegisterID fpReg, Assembler &masm) const
 {
-    if (fe->type.synced() && fe->data.synced()) {
-        masm.loadDouble(addressOf(fe), fpReg);
-        return;
-    }
-
     if (fe->isCopy()) {
         FrameEntry *backing = fe->copyOf();
-        if (backing->type.synced() && backing->data.synced()) {
+        if (backing->isCachedNumber() || (backing->type.synced() && backing->data.synced())) {
             masm.loadDouble(addressOf(backing), fpReg);
             return;
         }
         fe = backing;
     }
 
+    if ((fe->type.synced() && fe->data.synced()) || fe->isCachedNumber()) {
+        masm.loadDouble(addressOf(fe), fpReg);
+        return;
+    }
+
     Address address = addressOf(fe);
     do {
         if (!fe->data.synced()) {
             syncData(fe, address, masm);
             if (fe->isConstant())
                 break;
         }
         if (!fe->type.synced())
--- a/js/src/methodjit/FrameState.cpp
+++ b/js/src/methodjit/FrameState.cpp
@@ -709,16 +709,17 @@ FrameState::pushCopyOf(uint32 index)
     fe->resetUnsynced();
     if (backing->isConstant()) {
         fe->setConstant(Jsvalify(backing->getValue()));
     } else {
         if (backing->isTypeKnown())
             fe->setType(backing->getKnownType());
         else
             fe->type.invalidate();
+        fe->isNumber = backing->isNumber;
         fe->data.invalidate();
         if (backing->isCopy()) {
             backing = backing->copyOf();
             fe->setCopyOf(backing);
         } else {
             fe->setCopyOf(backing);
             backing->setCopied();
         }
@@ -867,16 +868,17 @@ FrameState::storeLocal(uint32 n, bool po
                 swapInTracker(backing, localFe);
             localFe->setNotCopied();
             localFe->setCopyOf(backing);
             if (backing->isTypeKnown())
                 localFe->setType(backing->getKnownType());
             else
                 localFe->type.invalidate();
             localFe->data.invalidate();
+            localFe->isNumber = backing->isNumber;
             return;
         }
 
         /*
          * If control flow lands here, then there was a bytecode sequence like
          *
          *  ENTERBLOCK 2
          *  GETLOCAL 1
@@ -933,16 +935,17 @@ FrameState::storeLocal(uint32 n, bool po
             masm.storeTypeTag(ImmType(backing->getKnownType()), addressOf(localFe));
         localFe->type.setMemory();
     }
 
     if (!backing->isTypeKnown())
         backing->type.invalidate();
     backing->data.invalidate();
     backing->setCopyOf(localFe);
+    backing->isNumber = localFe->isNumber;
     localFe->setCopied();
 
     JS_ASSERT(top->copyOf() == localFe);
 }
 
 void
 FrameState::shimmy(uint32 n)
 {
--- a/js/src/methodjit/FrameState.h
+++ b/js/src/methodjit/FrameState.h
@@ -242,16 +242,21 @@ class FrameState
      * the value it replaces on the stack had the same tag if the fast-path
      * was taken.
      */
     inline void pushUntypedPayload(JSValueType type, RegisterID payload,
                                    bool popGuaranteed = false,
                                    bool fastTyped = false);
 
     /*
+     * Pushes a number onto the operation stack.
+     */
+    inline void pushNumber(MaybeRegisterID payload);
+
+    /*
      * Pops a value off the operation stack, freeing any of its resources.
      */
     inline void pop();
 
     /*
      * Pops a number of values off the operation stack, freeing any of their
      * resources.
      */
--- a/js/src/methodjit/nunbox/FastArithmetic.cpp
+++ b/js/src/methodjit/nunbox/FastArithmetic.cpp
@@ -237,25 +237,26 @@ EmitDoubleOp(JSOp op, FPRegisterID fpRig
 mjit::Compiler::MaybeJump
 mjit::Compiler::loadDouble(FrameEntry *fe, FPRegisterID fpReg)
 {
     MaybeJump notNumber;
 
     if (fe->isConstant()) {
         slowLoadConstantDouble(masm, fe, fpReg);
     } else if (!fe->isTypeKnown()) {
-        //frame.tempRegForType(fe);
+        frame.tempRegForType(fe);
         Jump j = frame.testDouble(Assembler::Equal, fe);
         notNumber = frame.testInt32(Assembler::NotEqual, fe);
         frame.convertInt32ToDouble(masm, fe, fpReg);
         Jump converted = masm.jump();
         j.linkTo(masm.label(), &masm);
         frame.loadDouble(fe, fpReg, masm);
         converted.linkTo(masm.label(), &masm);
     } else if (fe->getKnownType() == JSVAL_TYPE_INT32) {
+        frame.tempRegForData(fe);
         frame.convertInt32ToDouble(masm, fe, fpReg);
     } else {
         JS_ASSERT(fe->getKnownType() == JSVAL_TYPE_DOUBLE);
         frame.loadDouble(fe, fpReg, masm);
     }
 
     return notNumber;
 }
@@ -285,17 +286,17 @@ mjit::Compiler::jsop_binary_double(Frame
         stubcc.linkExit(lhsNotNumber.get(), Uses(2));
     if (rhsNotNumber.isSet())
         stubcc.linkExit(rhsNotNumber.get(), Uses(2));
 
     stubcc.leave();
     stubcc.call(stub);
 
     frame.popn(2);
-    frame.pushSynced();
+    frame.pushNumber(MaybeRegisterID());
 
     stubcc.rejoin(Changes(1));
 }
 
 /*
  * Simpler version of jsop_binary_full() for when lhs == rhs.
  */
 void
@@ -303,17 +304,17 @@ mjit::Compiler::jsop_binary_full_simple(
 {
     FrameEntry *lhs = frame.peek(-2);
 
     /* Easiest case: known double. Don't bother conversion back yet? */
     if (fe->isTypeKnown() && fe->getKnownType() == JSVAL_TYPE_DOUBLE) {
         loadDouble(fe, FPRegisters::First);
         EmitDoubleOp(op, FPRegisters::First, FPRegisters::First, masm);
         frame.popn(2);
-        frame.pushSynced();
+        frame.pushNumber(MaybeRegisterID());
         return;
     }
 
     /* Allocate all registers up-front. */
     FrameState::BinaryAlloc regs;
     frame.allocForSameBinary(fe, op, regs);
 
     MaybeJump notNumber;
@@ -389,19 +390,21 @@ mjit::Compiler::jsop_binary_full_simple(
         notNumber.get().linkTo(stubcc.masm.label(), &stubcc.masm);
     overflowDone.get().linkTo(stubcc.masm.label(), &stubcc.masm);
 
     /* Slow call. */
     stubcc.syncExit(Uses(2));
     stubcc.leave();
     stubcc.call(stub);
 
+    masm.storeTypeTag(ImmType(JSVAL_TYPE_INT32), frame.addressOf(lhs));
+
     /* Finish up stack operations. */
     frame.popn(2);
-    frame.pushUntypedPayload(JSVAL_TYPE_INT32, regs.result);
+    frame.pushNumber(regs.result);
 
     /* Merge back OOL double paths. */
     if (doublePathDone.isSet())
         stubcc.linkRejoin(doublePathDone.get());
     stubcc.linkRejoin(overflowDone.get());
 
     stubcc.rejoin(Changes(1));
 }
@@ -639,19 +642,21 @@ mjit::Compiler::jsop_binary_full(FrameEn
     if (rhsNotNumber2.isSet())
         rhsNotNumber2.get().linkTo(stubcc.masm.label(), &stubcc.masm);
 
     /* Slow call. */
     stubcc.syncExit(Uses(2));
     stubcc.leave();
     stubcc.call(stub);
 
+    masm.storeTypeTag(ImmType(JSVAL_TYPE_INT32), frame.addressOf(lhs));
+
     /* Finish up stack operations. */
     frame.popn(2);
-    frame.pushUntypedPayload(JSVAL_TYPE_INT32, regs.result);
+    frame.pushNumber(regs.result);
 
     /* Merge back OOL double paths. */
     if (doublePathDone.isSet())
         stubcc.linkRejoin(doublePathDone.get());
     stubcc.linkRejoin(overflowDone.get());
 
     stubcc.rejoin(Changes(1));
 }