OSDN Git Service

merge in klp-release history after reset to klp-dev
[android-x86/dalvik.git] / vm / ReferenceTable.cpp
index adf3383..24180d4 100644 (file)
@@ -56,15 +56,15 @@ void dvmClearReferenceTable(ReferenceTable* pRef)
  */
 bool dvmAddToReferenceTable(ReferenceTable* pRef, Object* obj)
 {
-    assert(dvmIsValidObject(obj));
     assert(obj != NULL);
+    assert(dvmIsHeapAddress(obj));
     assert(pRef->table != NULL);
     assert(pRef->allocEntries <= pRef->maxEntries);
 
     if (pRef->nextEntry == pRef->table + pRef->allocEntries) {
         /* reached end of allocated space; did we hit buffer max? */
         if (pRef->nextEntry == pRef->table + pRef->maxEntries) {
-            LOGW("ReferenceTable overflow (max=%d)\n", pRef->maxEntries);
+            ALOGW("ReferenceTable overflow (max=%d)", pRef->maxEntries);
             return false;
         }
 
@@ -78,11 +78,11 @@ bool dvmAddToReferenceTable(ReferenceTable* pRef, Object* obj)
 
         newTable = (Object**) realloc(pRef->table, newSize * sizeof(Object*));
         if (newTable == NULL) {
-            LOGE("Unable to expand ref table (from %d to %d %d-byte entries)\n",
+            ALOGE("Unable to expand ref table (from %d to %d %d-byte entries)",
                 pRef->allocEntries, newSize, sizeof(Object*));
             return false;
         }
-        LOGVV("Growing %p from %d to %d\n", pRef, pRef->allocEntries, newSize);
+        LOGVV("Growing %p from %d to %d", pRef, pRef->allocEntries, newSize);
 
         /* update entries; adjust "nextEntry" in case memory moved */
         pRef->nextEntry = newTable + (pRef->nextEntry - pRef->table);
@@ -141,10 +141,10 @@ bool dvmRemoveFromReferenceTable(ReferenceTable* pRef, Object** bottom,
     if (moveCount != 0) {
         /* remove from middle, slide the rest down */
         memmove(ptr, ptr+1, moveCount * sizeof(Object*));
-        //LOGV("LREF delete %p, shift %d down\n", obj, moveCount);
+        //ALOGV("LREF delete %p, shift %d down", obj, moveCount);
     } else {
         /* last entry, falls off the end */
-        //LOGV("LREF delete %p from end\n", obj);
+        //ALOGV("LREF delete %p from end", obj);
     }
 
     return true;
@@ -157,8 +157,10 @@ bool dvmRemoveFromReferenceTable(ReferenceTable* pRef, Object** bottom,
 static size_t getElementCount(const Object* obj)
 {
     const ArrayObject* arrayObj = (ArrayObject*) obj;
-    if (arrayObj == NULL || arrayObj->clazz == NULL || !dvmIsArray(arrayObj))
+    if (arrayObj == NULL || arrayObj == kClearedJniWeakGlobal ||
+            arrayObj->clazz == NULL || !dvmIsArray(arrayObj)) {
         return 0;
+    }
     return arrayObj->length;
 }
 
@@ -171,7 +173,7 @@ static int compareObject(const void* vobj1, const void* vobj2)
     const Object* obj1 = *((Object* const*) vobj1);
     const Object* obj2 = *((Object* const*) vobj2);
 
-    /* ensure null references appear at the end */
+    // Ensure null references and cleared jweaks appear at the end.
     if (obj1 == NULL) {
         if (obj2 == NULL) {
             return 0;
@@ -181,6 +183,15 @@ static int compareObject(const void* vobj1, const void* vobj2)
     } else if (obj2 == NULL) {
         return -1;
     }
+    if (obj1 == kClearedJniWeakGlobal) {
+        if (obj2 == kClearedJniWeakGlobal) {
+            return 0;
+        } else {
+            return 1;
+        }
+    } else if (obj2 == kClearedJniWeakGlobal) {
+        return -1;
+    }
 
     if (obj1->clazz != obj2->clazz) {
         return (u1*)obj1->clazz - (u1*)obj2->clazz;
@@ -202,31 +213,33 @@ static int compareObject(const void* vobj1, const void* vobj2)
  * array object), and the number of additional objects that are identical
  * or equivalent to the original.
  */
-static void logObject(const Object* obj, size_t elems, int identical, int equiv)
+static void logSummaryLine(const Object* obj, size_t elems, int identical, int equiv)
 {
     if (obj == NULL) {
-        LOGW("  NULL reference (count=%d)\n", equiv);
+        ALOGW("    NULL reference (count=%d)", equiv);
+        return;
+    }
+    if (obj == kClearedJniWeakGlobal) {
+        ALOGW("    cleared jweak (count=%d)", equiv);
         return;
     }
 
-    /* handle "raw" dvmMalloc case */
-    const char* descriptor =
-        (obj->clazz != NULL) ? obj->clazz->descriptor : "(raw)";
-
-    char elemStr[16];
-
+    std::string className(dvmHumanReadableType(obj));
+    if (obj->clazz == gDvm.classJavaLangClass) {
+        // We're summarizing multiple instances, so using the exemplar
+        // Class' type parameter here would be misleading.
+        className = "java.lang.Class";
+    }
     if (elems != 0) {
-        snprintf(elemStr, sizeof(elemStr), " [%zd]", elems);
-    } else {
-        elemStr[0] = '\0';
+        StringAppendF(&className, " (%zd elements)", elems);
     }
 
+    size_t total = identical + equiv + 1;
+    std::string msg(StringPrintf("%5d of %s", total, className.c_str()));
     if (identical + equiv != 0) {
-        LOGW("%5d of %s%s (%d unique)\n", identical + equiv +1,
-            descriptor, elemStr, equiv +1);
-    } else {
-        LOGW("%5d of %s%s\n", identical + equiv +1, descriptor, elemStr);
+        StringAppendF(&msg, " (%d unique instances)", equiv + 1);
     }
+    ALOGW("    %s", msg.c_str());
 }
 
 /*
@@ -238,96 +251,110 @@ static void logObject(const Object* obj, size_t elems, int identical, int equiv)
 void dvmDumpReferenceTableContents(Object* const* refs, size_t count,
     const char* descr)
 {
+    ALOGW("%s reference table (%p) dump:", descr, refs);
+
     if (count == 0) {
-        LOGW("%s reference table has no entries\n", descr);
+        ALOGW("  (empty)");
         return;
     }
 
-    /*
-     * Dump the most recent N entries.
-     */
+    // Dump the most recent N entries.
     const size_t kLast = 10;
-    LOGW("Last %d entries in %s reference table:\n", kLast, descr);
-    int start = count - kLast;
-    if (start < 0)
-        start = 0;
-
-    size_t idx, elems;
-    for (idx = start; idx < count; idx++) {
+    int first = count - kLast;
+    if (first < 0) {
+        first = 0;
+    }
+    ALOGW("  Last %d entries (of %d):", (count - first), count);
+    for (int idx = count - 1; idx >= first; --idx) {
         const Object* ref = refs[idx];
-        if (ref == NULL)
+        if (ref == NULL) {
             continue;
-
-        elems = getElementCount(ref);
-
+        }
+        if (ref == kClearedJniWeakGlobal) {
+            ALOGW("    %5d: cleared jweak", idx);
+            continue;
+        }
         if (ref->clazz == NULL) {
-            /* should only be possible right after a plain dvmMalloc() */
+            // should only be possible right after a plain dvmMalloc().
             size_t size = dvmObjectSizeInHeap(ref);
-            LOGW("%5d: %p cls=(raw) (%zd bytes)\n", idx, ref, size);
-        } else if (dvmIsClassObject(ref)) {
-            ClassObject* clazz = (ClassObject*) ref;
-            LOGW("%5d: %p cls=%s '%s'\n", idx, ref, ref->clazz->descriptor,
-                clazz->descriptor);
-        } else if (elems != 0) {
-            LOGW("%5d: %p cls=%s [%zd]\n",
-                idx, ref, ref->clazz->descriptor, elems);
-        } else {
-            LOGW("%5d: %p cls=%s\n", idx, ref, ref->clazz->descriptor);
+            ALOGW("    %5d: %p (raw) (%zd bytes)", idx, ref, size);
+            continue;
         }
+
+        std::string className(dvmHumanReadableType(ref));
+
+        std::string extras;
+        size_t elems = getElementCount(ref);
+        if (elems != 0) {
+            StringAppendF(&extras, " (%zd elements)", elems);
+        } else if (ref->clazz == gDvm.classJavaLangString) {
+            const StringObject* str =
+                    reinterpret_cast<const StringObject*>(ref);
+            extras += " \"";
+            size_t count = 0;
+            char* s = dvmCreateCstrFromString(str);
+            char* p = s;
+            for (; *p && count < 16; ++p, ++count) {
+                extras += *p;
+            }
+            if (*p == 0) {
+                extras += "\"";
+            } else {
+                StringAppendF(&extras, "... (%d chars)", str->length());
+            }
+            free(s);
+        }
+        ALOGW("    %5d: %p %s%s", idx, ref, className.c_str(), extras.c_str());
     }
 
-    /*
-     * Make a copy of the table, and sort it.
-     */
+    // Make a copy of the table, and sort it.
     Object** tableCopy = (Object**)malloc(sizeof(Object*) * count);
     if (tableCopy == NULL) {
-        LOGE("Unable to copy table with %d elements\n", count);
+        ALOGE("Unable to copy table with %d elements", count);
         return;
     }
     memcpy(tableCopy, refs, sizeof(Object*) * count);
     qsort(tableCopy, count, sizeof(Object*), compareObject);
     refs = tableCopy;       // use sorted list
 
-    /*
-     * Find and remove any "holes" in the list.  The sort moved them all
-     * to the end.
-     *
-     * A table with nothing but NULL entries should have count==0, which
-     * was handled above, so this operation should not leave us with an
-     * empty list.
-     */
-    while (refs[count-1] == NULL) {
-        count--;
+    // Remove any uninteresting stuff from the list. The sort moved them all to the end.
+    while (count > 0 && refs[count-1] == NULL) {
+        --count;
+    }
+    while (count > 0 && refs[count-1] == kClearedJniWeakGlobal) {
+        --count;
+    }
+    if (count == 0) {
+        return;
     }
-    assert(count > 0);
 
-    /*
-     * Dump uniquified table summary.
-     */
-    LOGW("%s reference table summary (%d entries):\n", descr, count);
+    // Dump a summary of the whole table.
+    ALOGW("  Summary:");
     size_t equiv, identical;
     equiv = identical = 0;
+    size_t idx;
+    size_t elems;
     for (idx = 1; idx < count; idx++) {
         elems = getElementCount(refs[idx-1]);
 
         if (refs[idx] == refs[idx-1]) {
-            /* same reference, added more than once */
+            // same reference, added more than once.
             identical++;
         } else if (refs[idx]->clazz == refs[idx-1]->clazz &&
             getElementCount(refs[idx]) == elems)
         {
-            /* same class / element count, different object */
+            // same class / element count, different object.
             equiv++;
         } else {
-            /* different class */
-            logObject(refs[idx-1], elems, identical, equiv);
+            // different class.
+            logSummaryLine(refs[idx-1], elems, identical, equiv);
             equiv = identical = 0;
         }
     }
 
-    /* handle the last entry (everything above outputs refs[i-1]) */
+    // Handle the last entry (everything above outputs refs[i-1]).
     elems = getElementCount(refs[idx-1]);
-    logObject(refs[count-1], elems, identical, equiv);
+    logSummaryLine(refs[count-1], elems, identical, equiv);
 
     free(tableCopy);
 }