diff options
| -rw-r--r-- | vm/IndirectRefTable.c | 152 | ||||
| -rw-r--r-- | vm/IndirectRefTable.h | 2 | ||||
| -rw-r--r-- | vm/ReferenceTable.c | 102 | ||||
| -rw-r--r-- | vm/ReferenceTable.h | 8 |
4 files changed, 79 insertions, 185 deletions
diff --git a/vm/IndirectRefTable.c b/vm/IndirectRefTable.c index 8d7b3f94b..81cfeed4c 100644 --- a/vm/IndirectRefTable.c +++ b/vm/IndirectRefTable.c @@ -345,158 +345,10 @@ bool dvmRemoveFromIndirectRefTable(IndirectRefTable* pRef, u4 cookie, } /* - * This is a qsort() callback. We sort Object* by class, allocation size, - * and then by the Object* itself. - */ -static int compareObject(const void* vobj1, const void* vobj2) -{ - Object* obj1 = *((Object**) vobj1); - Object* obj2 = *((Object**) vobj2); - - /* ensure null references appear at the end */ - if (obj1 == NULL) { - if (obj2 == NULL) { - return 0; - } else { - return 1; - } - } else if (obj2 == NULL) { - return -1; - } - - if (obj1->clazz != obj2->clazz) { - return (u1*)obj1->clazz - (u1*)obj2->clazz; - } else { - int size1 = dvmObjectSizeInHeap(obj1); - int size2 = dvmObjectSizeInHeap(obj2); - if (size1 != size2) { - return size1 - size2; - } else { - return (u1*)obj1 - (u1*)obj2; - } - } -} - -/* - * Log an object with some additional info. - * - * Pass in the number of additional elements that are identical to or - * equivalent to the original. - */ -static void logObject(Object* obj, int size, int identical, int equiv) -{ - if (obj == NULL) { - LOGW(" NULL reference (count=%d)\n", equiv); - return; - } - - if (identical + equiv != 0) { - LOGW("%5d of %s %dB (%d unique)\n", identical + equiv +1, - obj->clazz->descriptor, size, equiv +1); - } else { - LOGW("%5d of %s %dB\n", identical + equiv +1, - obj->clazz->descriptor, size); - } -} - -/* * Dump the contents of a IndirectRefTable to the log. */ void dvmDumpIndirectRefTable(const IndirectRefTable* pRef, const char* descr) { - const int kLast = 10; - int count = dvmIndirectRefTableEntries(pRef); - Object** refs; - int i; - - if (count == 0) { - LOGW("Reference table has no entries\n"); - return; - } - assert(count > 0); - - /* - * Dump the most recent N entries. If there are holes, we will show - * fewer than N. - */ - LOGW("Last %d entries in %s reference table:\n", kLast, descr); - refs = pRef->table; // use unsorted list - int size; - int start = count - kLast; - if (start < 0) - start = 0; - - for (i = start; i < count; i++) { - if (refs[i] == NULL) - continue; - size = dvmObjectSizeInHeap(refs[i]); - Object* ref = refs[i]; - if (ref->clazz == gDvm.classJavaLangClass) { - ClassObject* clazz = (ClassObject*) ref; - LOGW("%5d: %p cls=%s '%s' (%d bytes)\n", i, ref, - (refs[i] == NULL) ? "-" : ref->clazz->descriptor, - clazz->descriptor, size); - } else { - LOGW("%5d: %p cls=%s (%d bytes)\n", i, ref, - (refs[i] == NULL) ? "-" : ref->clazz->descriptor, size); - } - } - - /* - * Make a copy of the table, and sort it. - * - * The NULL "holes" wind up at the end, so we can strip them off easily. - */ - Object** tableCopy = (Object**)malloc(sizeof(Object*) * count); - memcpy(tableCopy, pRef->table, sizeof(Object*) * count); - 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]); - } - - int holes = 0; - while (refs[count-1] == NULL) { - count--; - holes++; - } - - /* - * Dump uniquified table summary. While we're at it, generate a - * cumulative total amount of pinned memory based on the unique entries. - */ - LOGW("%s reference table summary (%d entries / %d holes):\n", - descr, count, holes); - int equiv, identical, total; - total = equiv = identical = 0; - for (i = 1; i < count; i++) { - size = dvmObjectSizeInHeap(refs[i-1]); - - if (refs[i] == refs[i-1]) { - /* same reference, added more than once */ - identical++; - } else if (refs[i]->clazz == refs[i-1]->clazz && - (int) dvmObjectSizeInHeap(refs[i]) == size) - { - /* same class / size, different object */ - total += size; - equiv++; - } else { - /* different class */ - total += size; - logObject(refs[i-1], size, identical, equiv); - equiv = identical = 0; - } - } - - /* handle the last entry (everything above outputs refs[i-1]) */ - size = (refs[count-1] == NULL) ? 0 : dvmObjectSizeInHeap(refs[count-1]); - total += size; - logObject(refs[count-1], size, identical, equiv); - - LOGW("Memory held directly by native code is %d bytes\n", total); - free(tableCopy); + dvmDumpReferenceTableContents(pRef->table, dvmIndirectRefTableEntries(pRef), + descr); } diff --git a/vm/IndirectRefTable.h b/vm/IndirectRefTable.h index f5157cb4f..c33a5095e 100644 --- a/vm/IndirectRefTable.h +++ b/vm/IndirectRefTable.h @@ -376,6 +376,8 @@ bool dvmRemoveFromIndirectRefTable(IndirectRefTable* pRef, u4 cookie, /* * Dump the contents of a reference table to the log file. + * + * The caller should lock any external sync before calling. */ void dvmDumpIndirectRefTable(const IndirectRefTable* pRef, const char* descr); diff --git a/vm/ReferenceTable.c b/vm/ReferenceTable.c index 8984d5f84..20d4d4677 100644 --- a/vm/ReferenceTable.c +++ b/vm/ReferenceTable.c @@ -156,11 +156,19 @@ bool dvmRemoveFromReferenceTable(ReferenceTable* pRef, Object** bottom, */ static int compareObject(const void* vobj1, const void* vobj2) { - Object* obj1 = *((Object**) vobj1); - Object* obj2 = *((Object**) vobj2); + const Object* obj1 = *((Object* const*) vobj1); + const Object* obj2 = *((Object* const*) vobj2); - if (obj1 == NULL || obj2 == NULL) - return (u1*)obj1 - (u1*)obj2; + /* ensure null references appear at the end */ + if (obj1 == NULL) { + if (obj2 == NULL) { + return 0; + } else { + return 1; + } + } else if (obj2 == NULL) { + return -1; + } if (obj1->clazz != obj2->clazz) { return (u1*)obj1->clazz - (u1*)obj2->clazz; @@ -181,7 +189,7 @@ static int compareObject(const void* vobj1, const void* vobj2) * Pass in the number of additional elements that are identical to or * equivalent to the original. */ -static void logObject(Object* obj, int size, int identical, int equiv) +static void logObject(const Object* obj, int size, int identical, int equiv) { if (obj == NULL) { LOGW(" NULL reference (count=%d)\n", equiv); @@ -201,19 +209,15 @@ static void logObject(Object* obj, int size, int identical, int equiv) } /* - * Dump the contents of a ReferenceTable to the log. - * - * The caller should lock any external sync before calling. + * Dump a summary of an array of references to the log file. * - * (This was originally written to be tolerant of null entries in the table. - * I don't think that can happen anymore.) + * This is used to dump the contents of ReferenceTable and IndirectRefTable + * structs. */ -void dvmDumpReferenceTable(const ReferenceTable* pRef, const char* descr) +void dvmDumpReferenceTableContents(Object* const* refs, size_t count, + const char* descr) { - const int kLast = 10; - int count = dvmReferenceTableEntries(pRef); - Object** refs; - int i; + const size_t kLast = 10; if (count == 0) { LOGW("%s reference table has no entries\n", descr); @@ -225,26 +229,27 @@ void dvmDumpReferenceTable(const ReferenceTable* pRef, const char* descr) * Dump the most recent N entries. */ LOGW("Last %d entries in %s reference table:\n", kLast, descr); - refs = pRef->table; // use unsorted list - int size; + size_t size, idx; int start = count - kLast; if (start < 0) start = 0; - for (i = start; i < count; i++) { - size = (refs[i] == NULL) ? 0 : dvmObjectSizeInHeap(refs[i]); - Object* ref = refs[i]; + for (idx = start; idx < count; idx++) { + if (refs[idx] == NULL) + continue; + size = dvmObjectSizeInHeap(refs[idx]); + const Object* ref = refs[idx]; if (ref->clazz == gDvm.classJavaLangClass) { ClassObject* clazz = (ClassObject*) ref; - LOGW("%5d: %p cls=%s '%s' (%d bytes)\n", i, ref, - (refs[i] == NULL) ? "-" : ref->clazz->descriptor, + LOGW("%5d: %p cls=%s '%s' (%d bytes)\n", idx, ref, + (refs[idx] == NULL) ? "-" : ref->clazz->descriptor, clazz->descriptor, size); } else if (ref->clazz == NULL) { /* should only be possible right after a plain dvmMalloc() */ - LOGW("%5d: %p cls=(raw) (%d bytes)\n", i, ref, size); + LOGW("%5d: %p cls=(raw) (%d bytes)\n", idx, ref, size); } else { - LOGW("%5d: %p cls=%s (%d bytes)\n", i, ref, - (refs[i] == NULL) ? "-" : ref->clazz->descriptor, size); + LOGW("%5d: %p cls=%s (%d bytes)\n", idx, ref, + (refs[idx] == NULL) ? "-" : ref->clazz->descriptor, size); } } @@ -252,25 +257,43 @@ void dvmDumpReferenceTable(const ReferenceTable* pRef, const char* descr) * Make a copy of the table, and sort it. */ Object** tableCopy = (Object**)malloc(sizeof(Object*) * count); - memcpy(tableCopy, pRef->table, sizeof(Object*) * count); + if (tableCopy == NULL) { + LOGE("Unable to copy table with %d elements\n", 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--; + } + assert(count > 0); + + /* * Dump uniquified table summary. While we're at it, generate a - * cumulative total amount of pinned memory based on the unique entries. + * cumulative total amount of referenced memory based on the unique + * entries. */ LOGW("%s reference table summary (%d entries):\n", descr, count); - int equiv, identical, total; + size_t equiv, identical, total; total = equiv = identical = 0; - for (i = 1; i < count; i++) { - size = (refs[i-1] == NULL) ? 0 : dvmObjectSizeInHeap(refs[i-1]); + for (idx = 1; idx < count; idx++) { + size = dvmObjectSizeInHeap(refs[idx-1]); - if (refs[i] == refs[i-1]) { + if (refs[idx] == refs[idx-1]) { /* same reference, added more than once */ identical++; - } else if (refs[i]->clazz == refs[i-1]->clazz && - (int) dvmObjectSizeInHeap(refs[i]) == size) + } else if (refs[idx]->clazz == refs[idx-1]->clazz && + dvmObjectSizeInHeap(refs[idx]) == size) { /* same class / size, different object */ total += size; @@ -278,16 +301,25 @@ void dvmDumpReferenceTable(const ReferenceTable* pRef, const char* descr) } else { /* different class */ total += size; - logObject(refs[i-1], size, identical, equiv); + logObject(refs[idx-1], size, identical, equiv); equiv = identical = 0; } } /* handle the last entry (everything above outputs refs[i-1]) */ - size = (refs[count-1] == NULL) ? 0 : dvmObjectSizeInHeap(refs[count-1]); + size = dvmObjectSizeInHeap(refs[count-1]); total += size; logObject(refs[count-1], size, identical, equiv); LOGW("Memory held directly by tracked refs is %d bytes\n", total); free(tableCopy); } + +/* + * Dump the contents of a ReferenceTable to the log. + */ +void dvmDumpReferenceTable(const ReferenceTable* pRef, const char* descr) +{ + dvmDumpReferenceTableContents(pRef->table, dvmReferenceTableEntries(pRef), + descr); +} diff --git a/vm/ReferenceTable.h b/vm/ReferenceTable.h index d6e2d705a..f434f554d 100644 --- a/vm/ReferenceTable.h +++ b/vm/ReferenceTable.h @@ -111,7 +111,15 @@ bool dvmRemoveFromReferenceTable(ReferenceTable* pRef, Object** bottom, /* * Dump the contents of a reference table to the log file. + * + * The caller should lock any external sync before calling. */ void dvmDumpReferenceTable(const ReferenceTable* pRef, const char* descr); +/* + * Internal function, shared with IndirectRefTable. + */ +void dvmDumpReferenceTableContents(Object* const* refs, size_t count, + const char* descr); + #endif /*_DALVIK_REFERENCETABLE*/ |
