Minor debugging tweaks to IndirectRefTable.

Added serial number checks, fixed tests, updated logging.
diff --git a/vm/IndirectRefTable.c b/vm/IndirectRefTable.c
index f7c7647..bea0a0f 100644
--- a/vm/IndirectRefTable.c
+++ b/vm/IndirectRefTable.c
@@ -35,6 +35,12 @@
 #ifndef NDEBUG
     memset(pRef->table, 0xd1, initialCount * sizeof(Object*));
 #endif
+
+    pRef->slotData =
+        (IndirectRefSlot*) calloc(maxCount, sizeof(IndirectRefSlot));
+    if (pRef->slotData == NULL)
+        return false;
+
     pRef->segmentState.all = IRT_FIRST_SEGMENT;
     pRef->allocEntries = initialCount;
     pRef->maxEntries = maxCount;
@@ -79,8 +85,8 @@
         return false;
     }
 
-    LOGV("--- after pop, top=%d holes=%d\n",
-        sst.parts.topIndex, sst.parts.numHoles);
+    LOGV("IRT %p[%d]: pop, top=%d holes=%d\n",
+        pRef, pRef->kind, sst.parts.topIndex, sst.parts.numHoles);
 
     return true;
 }
@@ -91,15 +97,45 @@
 static bool checkEntry(IndirectRefTable* pRef, IndirectRef iref, int idx)
 {
     Object* obj = pRef->table[idx];
-    IndirectRef checkRef = dvmObjectToIndirectRef(obj, idx, pRef->kind);
+    IndirectRef checkRef = dvmObjectToIndirectRef(pRef, obj, idx, pRef->kind);
     if (checkRef != iref) {
-        LOGW("iref mismatch: %p vs %p\n", iref, checkRef);
+        LOGW("IRT %p[%d]: iref mismatch (req=%p vs cur=%p)\n",
+            pRef, pRef->kind, iref, checkRef);
         return false;
     }
     return true;
 }
 
 /*
+ * Update extended debug info when an entry is added.
+ *
+ * We advance the serial number, invalidating any outstanding references to
+ * this slot.
+ */
+static inline void updateSlotAdd(IndirectRefTable* pRef, Object* obj, int slot)
+{
+    if (pRef->slotData != NULL) {
+        IndirectRefSlot* pSlot = &pRef->slotData[slot];
+        pSlot->serial++;
+        //LOGI("+++ add [%d] slot %d (%p->%p), serial=%d\n",
+        //    pRef->kind, slot, obj, iref, pSlot->serial);
+        pSlot->previous[pSlot->serial % kIRTPrevCount] = obj;
+    }
+}
+
+/*
+ * Update extended debug info when an entry is removed.
+ */
+static inline void updateSlotRemove(IndirectRefTable* pRef, int slot)
+{
+    if (pRef->slotData != NULL) {
+        IndirectRefSlot* pSlot = &pRef->slotData[slot];
+        //LOGI("+++ remove [%d] slot %d, serial now %d\n",
+        //    pRef->kind, slot, pSlot->serial);
+    }
+}
+
+/*
  * Add "obj" to "pRef".
  */
 IndirectRef dvmAddToIndirectRefTable(IndirectRefTable* pRef, u4 cookie,
@@ -161,12 +197,15 @@
         while (*--pScan != NULL) {
             assert(pScan >= pRef->table + bottomIndex);
         }
-        result = dvmObjectToIndirectRef(obj, pScan - pRef->table, pRef->kind);
+        updateSlotAdd(pRef, obj, pScan - pRef->table);
+        result = dvmObjectToIndirectRef(pRef, obj, pScan - pRef->table,
+            pRef->kind);
         *pScan = obj;
         pRef->segmentState.parts.numHoles--;
     } else {
         /* add to the end */
-        result = dvmObjectToIndirectRef(obj, topIndex, pRef->kind);
+        updateSlotAdd(pRef, obj, topIndex);
+        result = dvmObjectToIndirectRef(pRef, obj, topIndex, pRef->kind);
         pRef->table[topIndex++] = obj;
         pRef->segmentState.parts.topIndex = topIndex;
     }
@@ -220,6 +259,9 @@
  * specified by the cookie, we don't remove anything.  This is the behavior
  * required by JNI's DeleteLocalRef function.
  *
+ * Note this is NOT called when a local frame is popped.  This is only used
+ * for explict single removals.
+ *
  * Returns "false" if nothing was removed.
  */
 bool dvmRemoveFromIndirectRefTable(IndirectRefTable* pRef, u4 cookie,
@@ -255,6 +297,7 @@
          */
         if (!checkEntry(pRef, iref, idx))
             return false;
+        updateSlotRemove(pRef, idx);
 
 #ifndef NDEBUG
         pRef->table[idx] = (IndirectRef) 0xd3d3d3d3;
@@ -290,6 +333,7 @@
         }
         if (!checkEntry(pRef, iref, idx))
             return false;
+        updateSlotRemove(pRef, idx);
 
         pRef->table[idx] = NULL;
         pRef->segmentState.parts.numHoles++;
@@ -408,7 +452,7 @@
     qsort(tableCopy, count, sizeof(Object*), compareObject);
     refs = tableCopy;       // use sorted list
 
-    {
+    if (false) {
         int q;
         for (q = 0; q < count; q++)
             LOGI("%d %p\n", q, refs[q]);