}
/*
+ * If "obj" is an array, return the number of elements in the array.
+ * Otherwise, return zero.
+ */
+static size_t getElementCount(const Object* obj)
+{
+ const ArrayObject* arrayObj = (ArrayObject*) obj;
+ if (arrayObj == NULL || arrayObj->obj.clazz == NULL || !dvmIsArray(arrayObj))
+ return 0;
+ return arrayObj->length;
+}
+
+/*
* This is a qsort() callback. We sort Object* by class, allocation size,
* and then by the Object* itself.
*/
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;
+ size_t count1 = getElementCount(obj1);
+ size_t count2 = getElementCount(obj2);
+ if (count1 != count2) {
+ return count1 - count2;
} 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.
+ * Pass in the number of elements in the array (or 0 if this is not an
+ * array object), and the number of additional objects that are identical
+ * or equivalent to the original.
*/
-static void logObject(const Object* obj, int size, int identical, int equiv)
+static void logObject(const Object* obj, size_t elems, int identical, int equiv)
{
if (obj == NULL) {
LOGW(" NULL reference (count=%d)\n", equiv);
const char* descriptor =
(obj->clazz != NULL) ? obj->clazz->descriptor : "(raw)";
+ char elemStr[16];
+
+ if (elems != 0) {
+ snprintf(elemStr, sizeof(elemStr), " [%zd]", elems);
+ } else {
+ elemStr[0] = '\0';
+ }
+
if (identical + equiv != 0) {
- LOGW("%5d of %s %dB (%d unique)\n", identical + equiv +1,
- descriptor, size, equiv +1);
+ LOGW("%5d of %s%s (%d unique)\n", identical + equiv +1,
+ descriptor, elemStr, equiv +1);
} else {
- LOGW("%5d of %s %dB\n", identical + equiv +1, descriptor, size);
+ LOGW("%5d of %s%s\n", identical + equiv +1, descriptor, elemStr);
}
}
void dvmDumpReferenceTableContents(Object* const* refs, size_t count,
const char* descr)
{
- const size_t kLast = 10;
-
if (count == 0) {
LOGW("%s reference table has no entries\n", descr);
return;
}
- assert(count > 0);
/*
* Dump the most recent N entries.
*/
+ const size_t kLast = 10;
LOGW("Last %d entries in %s reference table:\n", kLast, descr);
- size_t size, idx;
int start = count - kLast;
if (start < 0)
start = 0;
+ size_t idx, elems;
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", idx, ref,
- (refs[idx] == NULL) ? "-" : ref->clazz->descriptor,
- clazz->descriptor, size);
- } else if (ref->clazz == NULL) {
+ if (ref == NULL)
+ continue;
+
+ elems = getElementCount(ref);
+
+ if (ref->clazz == NULL) {
/* should only be possible right after a plain dvmMalloc() */
- LOGW("%5d: %p cls=(raw) (%d bytes)\n", idx, ref, size);
+ size_t size = dvmObjectSizeInHeap(ref);
+ LOGW("%5d: %p cls=(raw) (%zd bytes)\n", idx, ref, size);
+ } else if (ref->clazz == gDvm.classJavaLangClass) {
+ 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 (%d bytes)\n", idx, ref,
- (refs[idx] == NULL) ? "-" : ref->clazz->descriptor, size);
+ LOGW("%5d: %p cls=%s\n", idx, ref, ref->clazz->descriptor);
}
}
assert(count > 0);
/*
- * Dump uniquified table summary. While we're at it, generate a
- * cumulative total amount of referenced memory based on the unique
- * entries.
+ * Dump uniquified table summary.
*/
LOGW("%s reference table summary (%d entries):\n", descr, count);
- size_t equiv, identical, total;
- total = equiv = identical = 0;
+ size_t equiv, identical;
+ equiv = identical = 0;
for (idx = 1; idx < count; idx++) {
- size = dvmObjectSizeInHeap(refs[idx-1]);
+ elems = getElementCount(refs[idx-1]);
if (refs[idx] == refs[idx-1]) {
/* same reference, added more than once */
identical++;
} else if (refs[idx]->clazz == refs[idx-1]->clazz &&
- dvmObjectSizeInHeap(refs[idx]) == size)
+ getElementCount(refs[idx]) == elems)
{
- /* same class / size, different object */
- total += size;
+ /* same class / element count, different object */
equiv++;
} else {
/* different class */
- total += size;
- logObject(refs[idx-1], size, identical, equiv);
+ logObject(refs[idx-1], elems, identical, equiv);
equiv = identical = 0;
}
}
/* handle the last entry (everything above outputs refs[i-1]) */
- size = dvmObjectSizeInHeap(refs[count-1]);
- total += size;
- logObject(refs[count-1], size, identical, equiv);
+ elems = getElementCount(refs[idx-1]);
+ logObject(refs[count-1], elems, identical, equiv);
- LOGW("Memory held directly by tracked refs is %d bytes\n", total);
free(tableCopy);
}