Merge backout.
authorDavid Anderson <danderson@mozilla.com>
Mon, 06 Sep 2010 18:20:40 -0700
changeset 74558 88a85a48414dd09191f1c528156fe7db546521c5
parent 74556 b7c8e195de3b08d1b0553f99086d5d207f2e9760 (current diff)
parent 74557 e0d3bfc8656525c53eb88eba878ab1d929d1f11d (diff)
child 74560 c76ed2a6bb61e195e8d485879312bb8735869318
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
milestone2.0b6pre
Merge backout.
js/src/methodjit/FrameState.cpp
js/src/methodjit/FrameState.h
--- a/js/src/methodjit/FrameState.cpp
+++ b/js/src/methodjit/FrameState.cpp
@@ -303,103 +303,80 @@ FrameState::assertValidRegisterState() c
         JS_ASSERT(!regstate[i].isPinned());
         JS_ASSERT_IF(regstate[i].fe(), !freeRegs.hasReg(RegisterID(i)));
         JS_ASSERT_IF(regstate[i].fe(), regstate[i].fe()->isTracked());
     }
 }
 #endif
 
 void
-FrameState::syncFancy(Assembler &masm, Registers avail, FrameEntry *resumeAt,
+FrameState::syncFancy(Assembler &masm, Registers avail, uint32 resumeAt,
                       FrameEntry *bottom) const
 {
-    reifier.reset(&masm, avail, resumeAt, bottom);
+    /* :TODO: can be resumeAt? */
+    reifier.reset(&masm, avail, tracker.nentries, bottom);
 
-    for (FrameEntry *fe = resumeAt; fe >= bottom; fe--) {
-        if (!fe->isTracked())
+    for (uint32 i = resumeAt; i < tracker.nentries; i--) {
+        FrameEntry *fe = tracker[i];
+        if (fe >= sp)
             continue;
 
         reifier.sync(fe);
     }
 }
 
 void
 FrameState::sync(Assembler &masm, Uses uses) const
 {
-    if (!entries)
-        return;
-
-    /* Sync all registers up-front. */
-    for (uint32 i = 0; i < JSC::MacroAssembler::TotalRegisters; i++) {
-        RegisterID reg = RegisterID(i);
-        FrameEntry *fe = regstate[reg].usedBy();
-        if (!fe)
-            continue;
-
-        JS_ASSERT(fe->isTracked());
-
-        if (regstate[reg].type() == RematInfo::DATA) {
-            JS_ASSERT(fe->data.reg() == reg);
-            if (!fe->data.synced())
-                syncData(fe, addressOf(fe), masm);
-        } else {
-            JS_ASSERT(fe->type.reg() == reg);
-            if (!fe->type.synced())
-                syncType(fe, addressOf(fe), masm);
-        }
-    }
-
     /*
      * Keep track of free registers using a bitmask. If we have to drop into
      * syncFancy(), then this mask will help avoid eviction.
      */
     Registers avail(freeRegs);
     Registers temp(Registers::TempRegs);
 
     FrameEntry *bottom = sp - uses.nuses;
 
     if (inTryBlock)
-        bottom = entries;
+        bottom = NULL;
 
-    for (FrameEntry *fe = sp - 1; fe >= bottom; fe--) {
-        if (!fe->isTracked())
+    for (uint32 i = tracker.nentries - 1; i < tracker.nentries; i--) {
+        FrameEntry *fe = tracker[i];
+        if (fe >= sp)
             continue;
 
         Address address = addressOf(fe);
 
         if (!fe->isCopy()) {
-            /*
-             * If this |fe| has registers, track them as available. They've
-             * already been synced. Otherwise, see if a constant needs to be
-             * synced.
-             */
-            if (fe->data.inRegister()) {
+            /* Keep track of registers that can be clobbered. */
+            if (fe->data.inRegister())
                 avail.putReg(fe->data.reg());
-            } else if (!fe->data.synced()) {
+            if (fe->type.inRegister())
+                avail.putReg(fe->type.reg());
+
+            /* Sync. */
+            if (!fe->data.synced() && (fe->data.inRegister() || fe >= bottom)) {
                 syncData(fe, address, masm);
                 if (fe->isConstant())
                     continue;
             }
-
-            if (fe->type.inRegister())
-                avail.putReg(fe->type.reg());
-            else if (!fe->type.synced())
-                syncType(fe, address, masm);
-        } else {
+            if (!fe->type.synced() && (fe->type.inRegister() || fe >= bottom))
+                syncType(fe, addressOf(fe), masm);
+        } else if (fe >= bottom) {
             FrameEntry *backing = fe->copyOf();
             JS_ASSERT(backing != fe);
             JS_ASSERT(!backing->isConstant() && !fe->isConstant());
 
             /*
              * If the copy is backed by something not in a register, fall back
              * to a slower sync algorithm.
              */
             if ((!fe->type.synced() && !backing->type.inRegister()) ||
                 (!fe->data.synced() && !backing->data.inRegister())) {
-                syncFancy(masm, avail, fe, bottom);
+                syncFancy(masm, avail, i, bottom);
                 return;
             }
 
             if (!fe->type.synced()) {
                 /* :TODO: we can do better, the type is learned for all copies. */
                 if (fe->isTypeKnown()) {
                     //JS_ASSERT(fe->getTypeTag() == backing->getTypeTag());
                     masm.storeTypeTag(ImmType(fe->getKnownType()), address);
--- a/js/src/methodjit/FrameState.h
+++ b/js/src/methodjit/FrameState.h
@@ -766,17 +766,17 @@ class FrameState
     inline void addToTracker(FrameEntry *fe);
     inline void syncType(const FrameEntry *fe, Address to, Assembler &masm) const;
     inline void syncData(const FrameEntry *fe, Address to, Assembler &masm) const;
     inline FrameEntry *getLocal(uint32 slot);
     inline void forgetAllRegs(FrameEntry *fe);
     inline void swapInTracker(FrameEntry *lhs, FrameEntry *rhs);
     inline uint32 localIndex(uint32 n);
     void pushCopyOf(uint32 index);
-    void syncFancy(Assembler &masm, Registers avail, FrameEntry *resumeAt,
+    void syncFancy(Assembler &masm, Registers avail, uint32 resumeAt,
                    FrameEntry *bottom) const;
     inline bool tryFastDoubleLoad(FrameEntry *fe, FPRegisterID fpReg, Assembler &masm) const;
     void resetInternalState();
 
     /*
      * "Uncopies" the backing store of a FrameEntry that has been copied. The
      * original FrameEntry is not invalidated; this is the responsibility of
      * the caller. The caller can check isCopied() to see if the registers
@@ -794,17 +794,17 @@ class FrameState
     RegisterID evictSomeReg() {
         return evictSomeReg(Registers::AvailRegs);
     }
 
     uint32 indexOf(int32 depth) {
         return uint32((sp + depth) - entries);
     }
 
-    uint32 indexOfFe(FrameEntry *fe) const {
+    uint32 indexOfFe(FrameEntry *fe) {
         return uint32(fe - entries);
     }
 
   private:
     JSContext *cx;
     JSScript *script;
     uint32 nargs;
     Assembler &masm;
--- a/js/src/methodjit/ImmutableSync.cpp
+++ b/js/src/methodjit/ImmutableSync.cpp
@@ -40,40 +40,41 @@
 #include "FrameState.h"
 #include "FrameState-inl.h"
 #include "ImmutableSync.h"
 
 using namespace js;
 using namespace js::mjit;
 
 ImmutableSync::ImmutableSync(JSContext *cx, const FrameState &frame)
-  : cx(cx), entries(NULL), frame(frame), generation(0)
+  : cx(cx), entries(NULL), frame(frame)
 {
 }
 
 ImmutableSync::~ImmutableSync()
 {
     cx->free(entries);
 }
 
 bool
 ImmutableSync::init(uint32 nentries)
 {
-    entries = (SyncEntry *)cx->calloc(sizeof(SyncEntry) * nentries);
+    entries = (SyncEntry *)cx->malloc(sizeof(SyncEntry) * nentries);
     return !!entries;
 }
 
 void
-ImmutableSync::reset(Assembler *masm, Registers avail, FrameEntry *top, FrameEntry *bottom)
+ImmutableSync::reset(Assembler *masm, Registers avail, uint32 n,
+                     FrameEntry *bottom)
 {
     this->avail = avail;
+    this->nentries = n;
     this->masm = masm;
-    this->top = top;
     this->bottom = bottom;
-    this->generation++;
+    memset(entries, 0, sizeof(SyncEntry) * nentries);
     memset(regs, 0, sizeof(regs));
 }
 
 JSC::MacroAssembler::RegisterID
 ImmutableSync::allocReg()
 {
     if (!avail.empty())
         return avail.takeAnyReg();
@@ -90,36 +91,47 @@ ImmutableSync::allocReg()
         lastResort = 0;
 
         if (!regs[i]) {
             /* If the frame does not own this register, take it! */
             FrameEntry *fe = frame.regstate[i].fe();
             if (!fe)
                 return reg;
 
+            /*
+             * The Reifier does not own this register, but the frame does.
+             * This must mean that we've not yet processed this entry, and
+             * that it's data has not been clobbered.
+             */
+            JS_ASSERT(fe->trackerIndex() < nentries);
+
             evictFromFrame = i;
 
             /*
              * If not copied, we can sync and not have to load again later.
              * That's about as good as it gets, so just break out now.
              */
             if (!fe->isCopied())
                 break;
         }
     }
 
     if (evictFromFrame != FrameState::InvalidIndex) {
         FrameEntry *fe = frame.regstate[evictFromFrame].fe();
         SyncEntry &e = entryFor(fe);
         if (frame.regstate[evictFromFrame].type() == RematInfo::TYPE) {
             JS_ASSERT(!e.typeClobbered);
+            e.typeSynced = true;
             e.typeClobbered = true;
+            masm->storeTypeTag(fe->type.reg(), frame.addressOf(fe));
         } else {
             JS_ASSERT(!e.dataClobbered);
+            e.dataSynced = true;
             e.dataClobbered = true;
+            masm->storePayload(fe->data.reg(), frame.addressOf(fe));
         }
         return RegisterID(evictFromFrame);
     }
 
     JS_ASSERT(lastResort != FrameState::InvalidIndex);
     JS_ASSERT(regs[lastResort]);
 
     SyncEntry *e = regs[lastResort];
@@ -133,48 +145,49 @@ ImmutableSync::allocReg()
     }
 
     return reg;
 }
 
 inline ImmutableSync::SyncEntry &
 ImmutableSync::entryFor(FrameEntry *fe)
 {
-    JS_ASSERT(fe <= top);
-    SyncEntry &e = entries[frame.indexOfFe(fe)];
-    if (e.generation != generation)
-        e.reset(generation);
-    return e;
+    JS_ASSERT(fe->trackerIndex() < nentries);
+    return entries[fe->trackerIndex()];
 }
 
 void
 ImmutableSync::sync(FrameEntry *fe)
 {
-#ifdef DEBUG
-    top = fe;
-#endif
-
+    JS_ASSERT(nentries);
     if (fe->isCopy())
         syncCopy(fe);
     else
         syncNormal(fe);
+    nentries--;
 }
 
 bool
 ImmutableSync::shouldSyncType(FrameEntry *fe, SyncEntry &e)
 {
-    /* Registers are synced up-front. */
-    return !fe->type.synced() && !fe->type.inRegister();
+    if (fe->type.inRegister() && !e.typeClobbered)
+        return true;
+    if (e.hasTypeReg)
+        return true;
+    return frame.inTryBlock || fe >= bottom;
 }
 
 bool
 ImmutableSync::shouldSyncData(FrameEntry *fe, SyncEntry &e)
 {
-    /* Registers are synced up-front. */
-    return !fe->data.synced() && !fe->data.inRegister();
+    if (fe->data.inRegister() && !e.dataClobbered)
+        return true;
+    if (e.hasDataReg)
+        return true;
+    return frame.inTryBlock || fe >= bottom;
 }
 
 JSC::MacroAssembler::RegisterID
 ImmutableSync::ensureTypeReg(FrameEntry *fe, SyncEntry &e)
 {
     if (fe->type.inRegister() && !e.typeClobbered)
         return fe->type.reg();
     if (e.hasTypeReg)
@@ -198,17 +211,18 @@ ImmutableSync::ensureDataReg(FrameEntry 
     regs[e.dataReg] = &e;
     masm->loadPayload(frame.addressOf(fe), e.dataReg);
     return e.dataReg;
 }
 
 void
 ImmutableSync::syncCopy(FrameEntry *fe)
 {
-    JS_ASSERT(fe >= bottom || frame.inTryBlock);
+    if (!frame.inTryBlock && fe < bottom)
+        return;
 
     FrameEntry *backing = fe->copyOf();
     SyncEntry &e = entryFor(backing);
 
     JS_ASSERT(!backing->isConstant());
 
     Address addr = frame.addressOf(fe);
 
@@ -235,25 +249,25 @@ ImmutableSync::syncNormal(FrameEntry *fe
 
     Address addr = frame.addressOf(fe);
 
     if (fe->isTypeKnown()) {
         e.learnedType = true;
         e.type = fe->getKnownType();
     }
 
-    if (shouldSyncData(fe, e)) {
+    if (!fe->data.synced() && !e.dataSynced && shouldSyncData(fe, e)) {
         if (fe->isConstant()) {
             masm->storeValue(fe->getValue(), addr);
             return;
         }
         masm->storePayload(ensureDataReg(fe, e), addr);
     }
 
-    if (shouldSyncType(fe, e)) {
+    if (!fe->type.synced() && !e.typeSynced && shouldSyncType(fe, e)) {
         if (e.learnedType)
             masm->storeTypeTag(ImmType(e.type), addr);
         else
             masm->storeTypeTag(ensureTypeReg(fe, e), addr);
     }
 
     if (e.hasDataReg) {
         avail.putReg(e.dataReg);
--- a/js/src/methodjit/ImmutableSync.h
+++ b/js/src/methodjit/ImmutableSync.h
@@ -65,42 +65,35 @@ class ImmutableSync
 
     struct SyncEntry {
         /*
          * NB: clobbered and sync mean the same thing: the register associated
          * in the FrameEntry is no longer valid, and has been written back.
          *
          * They are separated for readability.
          */
-        uint32 generation;
+        bool dataSynced;
+        bool typeSynced;
         bool dataClobbered;
         bool typeClobbered;
+        RegisterID dataReg;
+        RegisterID typeReg;
         bool hasDataReg;
         bool hasTypeReg;
         bool learnedType;
-        RegisterID dataReg;
-        RegisterID typeReg;
         JSValueType type;
-
-        void reset(uint32 gen) {
-            dataClobbered = false;
-            typeClobbered = false;
-            hasDataReg = false;
-            hasTypeReg = false;
-            learnedType = false;
-            generation = gen;
-        }
     };
 
   public:
     ImmutableSync(JSContext *cx, const FrameState &frame);
     ~ImmutableSync();
     bool init(uint32 nentries);
 
-    void reset(Assembler *masm, Registers avail, FrameEntry *top, FrameEntry *bottom);
+    void reset(Assembler *masm, Registers avail, uint32 n,
+               FrameEntry *bottom);
     void sync(FrameEntry *fe);
 
   private:
     void syncCopy(FrameEntry *fe);
     void syncNormal(FrameEntry *fe);
     RegisterID ensureDataReg(FrameEntry *fe, SyncEntry &e);
     RegisterID ensureTypeReg(FrameEntry *fe, SyncEntry &e);
     RegisterID allocReg();
@@ -113,18 +106,16 @@ class ImmutableSync
   private:
     JSContext *cx;
     SyncEntry *entries;
     const FrameState &frame;
     uint32 nentries;
     Registers avail;
     Assembler *masm;
     SyncEntry *regs[Assembler::TotalRegisters];
-    FrameEntry *top;
     FrameEntry *bottom;
-    uint32 generation;
 };
 
 } /* namespace mjit */
 } /* namespace js */
 
 #endif /* jsjaeger_imm_sync_h__ */