ReferenceTable.cpp revision da2013fc08907c89084d1ff21e51302f871a0796
1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Reference table management. 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h" 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize a ReferenceTable structure. 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmInitReferenceTable(ReferenceTable* pRef, int initialCount, 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int maxCount) 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(initialCount > 0); 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(initialCount <= maxCount); 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pRef->table = (Object**) malloc(initialCount * sizeof(Object*)); 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pRef->table == NULL) 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(pRef->table, 0xdd, initialCount * sizeof(Object*)); 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pRef->nextEntry = pRef->table; 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pRef->allocEntries = initialCount; 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pRef->maxEntries = maxCount; 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clears out the contents of a ReferenceTable, freeing allocated storage. 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmClearReferenceTable(ReferenceTable* pRef) 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pRef->table); 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pRef->table = pRef->nextEntry = NULL; 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pRef->allocEntries = pRef->maxEntries = -1; 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add "obj" to "pRef". 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmAddToReferenceTable(ReferenceTable* pRef, Object* obj) 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsValidObject(obj)); 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj != NULL); 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(pRef->table != NULL); 62734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(pRef->allocEntries <= pRef->maxEntries); 63734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 64734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (pRef->nextEntry == pRef->table + pRef->allocEntries) { 65734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* reached end of allocated space; did we hit buffer max? */ 66734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (pRef->nextEntry == pRef->table + pRef->maxEntries) { 67734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGW("ReferenceTable overflow (max=%d)\n", pRef->maxEntries); 68734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return false; 69734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object** newTable; 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int newSize; 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newSize = pRef->allocEntries * 2; 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (newSize > pRef->maxEntries) 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newSize = pRef->maxEntries; 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(newSize > pRef->allocEntries); 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newTable = (Object**) realloc(pRef->table, newSize * sizeof(Object*)); 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (newTable == NULL) { 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Unable to expand ref table (from %d to %d %d-byte entries)\n", 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pRef->allocEntries, newSize, sizeof(Object*)); 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("Growing %p from %d to %d\n", pRef, pRef->allocEntries, newSize); 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* update entries; adjust "nextEntry" in case memory moved */ 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pRef->nextEntry = newTable + (pRef->nextEntry - pRef->table); 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pRef->table = newTable; 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pRef->allocEntries = newSize; 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *pRef->nextEntry++ = obj; 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL if not found. 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 100d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenObject** dvmFindInReferenceTable(const ReferenceTable* pRef, Object** bottom, 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* obj) 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object** ptr; 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ptr = pRef->nextEntry; 106d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden while (--ptr >= bottom) { 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (*ptr == obj) 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return ptr; 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Remove "obj" from "pRef". We start at the end of the list (where the 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * most-recently-added element is), and stop searching for a match after 116d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * examining the element at "bottom". 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Most of the time "obj" is at or near the end of the list. If not, we 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * compact it down. 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 121d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFaddenbool dvmRemoveFromReferenceTable(ReferenceTable* pRef, Object** bottom, 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* obj) 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object** ptr; 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(pRef->table != NULL); 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 129d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden * Scan from the most-recently-added entry up to the bottom entry for 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this frame. 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 132d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden ptr = dvmFindInReferenceTable(pRef, bottom, obj); 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (ptr == NULL) 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Delete the entry. 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pRef->nextEntry--; 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int moveCount = pRef->nextEntry - ptr; 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (moveCount != 0) { 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* remove from middle, slide the rest down */ 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memmove(ptr, ptr+1, moveCount * sizeof(Object*)); 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGV("LREF delete %p, shift %d down\n", obj, moveCount); 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* last entry, falls off the end */ 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGV("LREF delete %p from end\n", obj); 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is a qsort() callback. We sort Object* by class, allocation size, 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and then by the Object* itself. 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int compareObject(const void* vobj1, const void* vobj2) 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 159da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden const Object* obj1 = *((Object* const*) vobj1); 160da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden const Object* obj2 = *((Object* const*) vobj2); 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 162da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden /* ensure null references appear at the end */ 163da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden if (obj1 == NULL) { 164da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden if (obj2 == NULL) { 165da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden return 0; 166da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden } else { 167da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden return 1; 168da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden } 169da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden } else if (obj2 == NULL) { 170da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden return -1; 171da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden } 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (obj1->clazz != obj2->clazz) { 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (u1*)obj1->clazz - (u1*)obj2->clazz; 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int size1 = dvmObjectSizeInHeap(obj1); 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int size2 = dvmObjectSizeInHeap(obj2); 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (size1 != size2) { 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return size1 - size2; 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (u1*)obj1 - (u1*)obj2; 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Log an object with some additional info. 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in the number of additional elements that are identical to or 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * equivalent to the original. 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 192da2013fc08907c89084d1ff21e51302f871a0796Andy McFaddenstatic void logObject(const Object* obj, int size, int identical, int equiv) 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (obj == NULL) { 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW(" NULL reference (count=%d)\n", equiv); 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 199afcd1eb5034dcc3d424297ae282842252162661dAndy McFadden /* handle "raw" dvmMalloc case */ 200afcd1eb5034dcc3d424297ae282842252162661dAndy McFadden const char* descriptor = 201afcd1eb5034dcc3d424297ae282842252162661dAndy McFadden (obj->clazz != NULL) ? obj->clazz->descriptor : "(raw)"; 202afcd1eb5034dcc3d424297ae282842252162661dAndy McFadden 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (identical + equiv != 0) { 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("%5d of %s %dB (%d unique)\n", identical + equiv +1, 205afcd1eb5034dcc3d424297ae282842252162661dAndy McFadden descriptor, size, equiv +1); 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 207afcd1eb5034dcc3d424297ae282842252162661dAndy McFadden LOGW("%5d of %s %dB\n", identical + equiv +1, descriptor, size); 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 212da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden * Dump a summary of an array of references to the log file. 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 214da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden * This is used to dump the contents of ReferenceTable and IndirectRefTable 215da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden * structs. 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 217da2013fc08907c89084d1ff21e51302f871a0796Andy McFaddenvoid dvmDumpReferenceTableContents(Object* const* refs, size_t count, 218da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden const char* descr) 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 220da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden const size_t kLast = 10; 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (count == 0) { 22392fa476a8802023b443af893817eb14fef18aaeaAndy McFadden LOGW("%s reference table has no entries\n", descr); 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(count > 0); 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the most recent N entries. 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Last %d entries in %s reference table:\n", kLast, descr); 232da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden size_t size, idx; 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int start = count - kLast; 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (start < 0) 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start = 0; 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 237da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden for (idx = start; idx < count; idx++) { 238da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden if (refs[idx] == NULL) 239da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden continue; 240da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden size = dvmObjectSizeInHeap(refs[idx]); 241da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden const Object* ref = refs[idx]; 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (ref->clazz == gDvm.classJavaLangClass) { 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz = (ClassObject*) ref; 244da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden LOGW("%5d: %p cls=%s '%s' (%d bytes)\n", idx, ref, 245da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden (refs[idx] == NULL) ? "-" : ref->clazz->descriptor, 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz->descriptor, size); 247afcd1eb5034dcc3d424297ae282842252162661dAndy McFadden } else if (ref->clazz == NULL) { 248afcd1eb5034dcc3d424297ae282842252162661dAndy McFadden /* should only be possible right after a plain dvmMalloc() */ 249da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden LOGW("%5d: %p cls=(raw) (%d bytes)\n", idx, ref, size); 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 251da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden LOGW("%5d: %p cls=%s (%d bytes)\n", idx, ref, 252da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden (refs[idx] == NULL) ? "-" : ref->clazz->descriptor, size); 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Make a copy of the table, and sort it. 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object** tableCopy = (Object**)malloc(sizeof(Object*) * count); 260da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden if (tableCopy == NULL) { 261da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden LOGE("Unable to copy table with %d elements\n", count); 262da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden return; 263da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden } 264da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden memcpy(tableCopy, refs, sizeof(Object*) * count); 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project qsort(tableCopy, count, sizeof(Object*), compareObject); 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project refs = tableCopy; // use sorted list 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 269da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden * Find and remove any "holes" in the list. The sort moved them all 270da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden * to the end. 271da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden * 272da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden * A table with nothing but NULL entries should have count==0, which 273da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden * was handled above, so this operation should not leave us with an 274da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden * empty list. 275da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden */ 276da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden while (refs[count-1] == NULL) { 277da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden count--; 278da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden } 279da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden assert(count > 0); 280da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden 281da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden /* 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump uniquified table summary. While we're at it, generate a 283da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden * cumulative total amount of referenced memory based on the unique 284da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden * entries. 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("%s reference table summary (%d entries):\n", descr, count); 287da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden size_t equiv, identical, total; 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project total = equiv = identical = 0; 289da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden for (idx = 1; idx < count; idx++) { 290da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden size = dvmObjectSizeInHeap(refs[idx-1]); 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 292da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden if (refs[idx] == refs[idx-1]) { 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* same reference, added more than once */ 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project identical++; 295da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden } else if (refs[idx]->clazz == refs[idx-1]->clazz && 296da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden dvmObjectSizeInHeap(refs[idx]) == size) 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* same class / size, different object */ 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project total += size; 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project equiv++; 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* different class */ 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project total += size; 304da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden logObject(refs[idx-1], size, identical, equiv); 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project equiv = identical = 0; 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* handle the last entry (everything above outputs refs[i-1]) */ 310da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden size = dvmObjectSizeInHeap(refs[count-1]); 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project total += size; 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project logObject(refs[count-1], size, identical, equiv); 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 314afcd1eb5034dcc3d424297ae282842252162661dAndy McFadden LOGW("Memory held directly by tracked refs is %d bytes\n", total); 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(tableCopy); 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 317da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden 318da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden/* 319da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden * Dump the contents of a ReferenceTable to the log. 320da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden */ 321da2013fc08907c89084d1ff21e51302f871a0796Andy McFaddenvoid dvmDumpReferenceTable(const ReferenceTable* pRef, const char* descr) 322da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden{ 323da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden dvmDumpReferenceTableContents(pRef->table, dvmReferenceTableEntries(pRef), 324da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden descr); 325da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden} 326