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(obj != NULL); 608bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes assert(dvmIsHeapAddress(obj)); 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) { 67e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("ReferenceTable overflow (max=%d)", 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) { 81c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Unable to expand ref table (from %d to %d %d-byte entries)", 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pRef->allocEntries, newSize, sizeof(Object*)); 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 8560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("Growing %p from %d to %d", 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*)); 14492c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block //ALOGV("LREF delete %p, shift %d down", obj, moveCount); 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* last entry, falls off the end */ 14792c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block //ALOGV("LREF delete %p from end", 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/* 1544b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden * If "obj" is an array, return the number of elements in the array. 1554b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden * Otherwise, return zero. 1564b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden */ 1574b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFaddenstatic size_t getElementCount(const Object* obj) 1584b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden{ 1594b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden const ArrayObject* arrayObj = (ArrayObject*) obj; 160259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes if (arrayObj == NULL || arrayObj == kClearedJniWeakGlobal || 161259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes arrayObj->clazz == NULL || !dvmIsArray(arrayObj)) { 1624b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden return 0; 163259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes } 1644b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden return arrayObj->length; 1654b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden} 1664b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden 1674b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden/* 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is a qsort() callback. We sort Object* by class, allocation size, 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and then by the Object* itself. 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int compareObject(const void* vobj1, const void* vobj2) 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 173da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden const Object* obj1 = *((Object* const*) vobj1); 174da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden const Object* obj2 = *((Object* const*) vobj2); 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 176259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes // Ensure null references and cleared jweaks appear at the end. 177da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden if (obj1 == NULL) { 178da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden if (obj2 == NULL) { 179da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden return 0; 180da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden } else { 181da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden return 1; 182da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden } 183da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden } else if (obj2 == NULL) { 184da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden return -1; 185da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden } 186259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes if (obj1 == kClearedJniWeakGlobal) { 187259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes if (obj2 == kClearedJniWeakGlobal) { 188259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes return 0; 189259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes } else { 190259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes return 1; 191259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes } 192259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes } else if (obj2 == kClearedJniWeakGlobal) { 193259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes return -1; 194259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes } 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (obj1->clazz != obj2->clazz) { 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (u1*)obj1->clazz - (u1*)obj2->clazz; 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1994b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden size_t count1 = getElementCount(obj1); 2004b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden size_t count2 = getElementCount(obj2); 2014b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden if (count1 != count2) { 2024b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden return count1 - count2; 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (u1*)obj1 - (u1*)obj2; 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Log an object with some additional info. 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 2124b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden * Pass in the number of elements in the array (or 0 if this is not an 2134b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden * array object), and the number of additional objects that are identical 2144b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden * or equivalent to the original. 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 2167c08071765cb134e4c0b18bf8fd6a7060e145212Elliott Hughesstatic void logSummaryLine(const Object* obj, size_t elems, int identical, int equiv) 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (obj == NULL) { 219e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW(" NULL reference (count=%d)", equiv); 220259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes return; 221259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes } 222259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes if (obj == kClearedJniWeakGlobal) { 223e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW(" cleared jweak (count=%d)", equiv); 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 2277c08071765cb134e4c0b18bf8fd6a7060e145212Elliott Hughes std::string className(dvmHumanReadableType(obj)); 2287c08071765cb134e4c0b18bf8fd6a7060e145212Elliott Hughes if (obj->clazz == gDvm.classJavaLangClass) { 2297c08071765cb134e4c0b18bf8fd6a7060e145212Elliott Hughes // We're summarizing multiple instances, so using the exemplar 2307c08071765cb134e4c0b18bf8fd6a7060e145212Elliott Hughes // Class' type parameter here would be misleading. 2317c08071765cb134e4c0b18bf8fd6a7060e145212Elliott Hughes className = "java.lang.Class"; 2327c08071765cb134e4c0b18bf8fd6a7060e145212Elliott Hughes } 2337c08071765cb134e4c0b18bf8fd6a7060e145212Elliott Hughes if (elems != 0) { 2347c08071765cb134e4c0b18bf8fd6a7060e145212Elliott Hughes StringAppendF(&className, " (%zd elements)", elems); 2354b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden } 2364b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden 237fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes size_t total = identical + equiv + 1; 238837eabb829417c1542037423c55536649de404b8Elliott Hughes std::string msg(StringPrintf("%5d of %s", total, className.c_str())); 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (identical + equiv != 0) { 240837eabb829417c1542037423c55536649de404b8Elliott Hughes StringAppendF(&msg, " (%d unique instances)", equiv + 1); 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 242e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW(" %s", msg.c_str()); 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 246da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden * Dump a summary of an array of references to the log file. 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 248da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden * This is used to dump the contents of ReferenceTable and IndirectRefTable 249da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden * structs. 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 251da2013fc08907c89084d1ff21e51302f871a0796Andy McFaddenvoid dvmDumpReferenceTableContents(Object* const* refs, size_t count, 252da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden const char* descr) 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 254e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("%s reference table (%p) dump:", descr, refs); 255259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (count == 0) { 257e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW(" (empty)"); 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 261259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes // Dump the most recent N entries. 2624b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden const size_t kLast = 10; 263fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes int first = count - kLast; 264fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes if (first < 0) { 265fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes first = 0; 266fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes } 267e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW(" Last %d entries (of %d):", (count - first), count); 268fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes for (int idx = count - 1; idx >= first; --idx) { 269da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden const Object* ref = refs[idx]; 270fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes if (ref == NULL) { 2714b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden continue; 272fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes } 273259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes if (ref == kClearedJniWeakGlobal) { 274e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW(" %5d: cleared jweak", idx); 275259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes continue; 276259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes } 2774b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden if (ref->clazz == NULL) { 278259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes // should only be possible right after a plain dvmMalloc(). 2794b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden size_t size = dvmObjectSizeInHeap(ref); 280e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW(" %5d: %p (raw) (%zd bytes)", idx, ref, size); 281fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes continue; 282fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes } 283fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes 284fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes std::string className(dvmHumanReadableType(ref)); 285fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes 286fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes std::string extras; 287fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes size_t elems = getElementCount(ref); 288fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes if (elems != 0) { 289837eabb829417c1542037423c55536649de404b8Elliott Hughes StringAppendF(&extras, " (%zd elements)", elems); 290fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes } else if (ref->clazz == gDvm.classJavaLangString) { 291fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes const StringObject* str = 292fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes reinterpret_cast<const StringObject*>(ref); 293fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes extras += " \""; 294fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes size_t count = 0; 295fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes char* s = dvmCreateCstrFromString(str); 296fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes char* p = s; 297fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes for (; *p && count < 16; ++p, ++count) { 298fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes extras += *p; 299fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes } 300fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes if (*p == 0) { 301fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes extras += "\""; 302fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes } else { 303d8a3f9fa1951e552f5f65c2914689083cc0c46c2Elliott Hughes StringAppendF(&extras, "... (%d chars)", str->length()); 304fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes } 305fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes free(s); 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 307e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW(" %5d: %p %s%s", idx, ref, className.c_str(), extras.c_str()); 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 310259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes // Make a copy of the table, and sort it. 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object** tableCopy = (Object**)malloc(sizeof(Object*) * count); 312da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden if (tableCopy == NULL) { 313c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Unable to copy table with %d elements", count); 314da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden return; 315da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden } 316da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden memcpy(tableCopy, refs, sizeof(Object*) * count); 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project qsort(tableCopy, count, sizeof(Object*), compareObject); 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project refs = tableCopy; // use sorted list 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 320259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes // Remove any uninteresting stuff from the list. The sort moved them all to the end. 321259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes while (count > 0 && refs[count-1] == NULL) { 322259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes --count; 323259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes } 324259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes while (count > 0 && refs[count-1] == kClearedJniWeakGlobal) { 325259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes --count; 326259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes } 327259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes if (count == 0) { 328259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes return; 329da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden } 330da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden 331259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes // Dump a summary of the whole table. 332e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW(" Summary:"); 3334b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden size_t equiv, identical; 3344b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden equiv = identical = 0; 335fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes size_t idx; 336fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes size_t elems; 337da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden for (idx = 1; idx < count; idx++) { 3384b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden elems = getElementCount(refs[idx-1]); 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 340da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden if (refs[idx] == refs[idx-1]) { 341259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes // same reference, added more than once. 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project identical++; 343da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden } else if (refs[idx]->clazz == refs[idx-1]->clazz && 3444b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden getElementCount(refs[idx]) == elems) 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 346259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes // same class / element count, different object. 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project equiv++; 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 349259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes // different class. 3507c08071765cb134e4c0b18bf8fd6a7060e145212Elliott Hughes logSummaryLine(refs[idx-1], elems, identical, equiv); 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project equiv = identical = 0; 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 355259a8a5154c63a793ea0ee438d146acda7d990b6Elliott Hughes // Handle the last entry (everything above outputs refs[i-1]). 3564b74b47d2120d4f3fecc47d5dd62ac65708737e5Andy McFadden elems = getElementCount(refs[idx-1]); 3577c08071765cb134e4c0b18bf8fd6a7060e145212Elliott Hughes logSummaryLine(refs[count-1], elems, identical, equiv); 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(tableCopy); 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 361da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden 362da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden/* 363da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden * Dump the contents of a ReferenceTable to the log. 364da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden */ 365da2013fc08907c89084d1ff21e51302f871a0796Andy McFaddenvoid dvmDumpReferenceTable(const ReferenceTable* pRef, const char* descr) 366da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden{ 367da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden dvmDumpReferenceTableContents(pRef->table, dvmReferenceTableEntries(pRef), 368da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden descr); 369da2013fc08907c89084d1ff21e51302f871a0796Andy McFadden} 370