X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=vm%2FReferenceTable.cpp;h=24180d4bf394e8e1eb668be8b4bb774fa5126b79;hb=c5d0614f778e0f26db913fdc7320f08e9417e984;hp=adf3383b6d5c7789f450176d3815dbd2231e8c55;hpb=bbf31b58c50fb892423b7fef0d8c1093bd0c1a6c;p=android-x86%2Fdalvik.git diff --git a/vm/ReferenceTable.cpp b/vm/ReferenceTable.cpp index adf3383b6..24180d4bf 100644 --- a/vm/ReferenceTable.cpp +++ b/vm/ReferenceTable.cpp @@ -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(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); }