1734155efc18543eab20b763f9a315ab1a44240acAndy McFadden/* 2734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Copyright (C) 2009 The Android Open Source Project 3734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * 4734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Licensed under the Apache License, Version 2.0 (the "License"); 5734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * you may not use this file except in compliance with the License. 6734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * You may obtain a copy of the License at 7734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * 8734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * http://www.apache.org/licenses/LICENSE-2.0 9734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * 10734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Unless required by applicable law or agreed to in writing, software 11734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * distributed under the License is distributed on an "AS IS" BASIS, 12734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * See the License for the specific language governing permissions and 14734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * limitations under the License. 15734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 16734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 17734155efc18543eab20b763f9a315ab1a44240acAndy McFadden/* 18734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Indirect reference table management. 19734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 20734155efc18543eab20b763f9a315ab1a44240acAndy McFadden#include "Dalvik.h" 21734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 22734155efc18543eab20b763f9a315ab1a44240acAndy McFadden/* 23734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Initialize an IndirectRefTable structure. 24734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 25734155efc18543eab20b763f9a315ab1a44240acAndy McFaddenbool dvmInitIndirectRefTable(IndirectRefTable* pRef, int initialCount, 26734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int maxCount, IndirectRefKind kind) 27734155efc18543eab20b763f9a315ab1a44240acAndy McFadden{ 28734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(initialCount > 0); 29734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(initialCount <= maxCount); 30734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(kind == kIndirectKindLocal || kind == kIndirectKindGlobal); 31734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 32734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->table = (Object**) malloc(initialCount * sizeof(Object*)); 33734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (pRef->table == NULL) 34734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return false; 35734155efc18543eab20b763f9a315ab1a44240acAndy McFadden#ifndef NDEBUG 36734155efc18543eab20b763f9a315ab1a44240acAndy McFadden memset(pRef->table, 0xd1, initialCount * sizeof(Object*)); 37734155efc18543eab20b763f9a315ab1a44240acAndy McFadden#endif 385d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden 395d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden pRef->slotData = 405d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden (IndirectRefSlot*) calloc(maxCount, sizeof(IndirectRefSlot)); 415d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden if (pRef->slotData == NULL) 425d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden return false; 435d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden 44ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden pRef->segmentState.all = IRT_FIRST_SEGMENT; 45734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->allocEntries = initialCount; 46734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->maxEntries = maxCount; 47734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->kind = kind; 48734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 49734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return true; 50734155efc18543eab20b763f9a315ab1a44240acAndy McFadden} 51734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 52734155efc18543eab20b763f9a315ab1a44240acAndy McFadden/* 53734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Clears out the contents of a IndirectRefTable, freeing allocated storage. 54734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 55734155efc18543eab20b763f9a315ab1a44240acAndy McFaddenvoid dvmClearIndirectRefTable(IndirectRefTable* pRef) 56734155efc18543eab20b763f9a315ab1a44240acAndy McFadden{ 57734155efc18543eab20b763f9a315ab1a44240acAndy McFadden free(pRef->table); 58734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->table = NULL; 59734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->allocEntries = pRef->maxEntries = -1; 60734155efc18543eab20b763f9a315ab1a44240acAndy McFadden} 61734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 62734155efc18543eab20b763f9a315ab1a44240acAndy McFadden/* 63734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Remove one or more segments from the top. The table entry identified 64734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * by "cookie" becomes the new top-most entry. 65734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * 66734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Returns false if "cookie" is invalid or the table has only one segment. 67734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 68734155efc18543eab20b763f9a315ab1a44240acAndy McFaddenbool dvmPopIndirectRefTableSegmentCheck(IndirectRefTable* pRef, u4 cookie) 69734155efc18543eab20b763f9a315ab1a44240acAndy McFadden{ 70734155efc18543eab20b763f9a315ab1a44240acAndy McFadden IRTSegmentState sst; 71734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 72734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* 73734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * The new value for "top" must be <= the current value. Otherwise 74734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * this would represent an expansion of the table. 75734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 76734155efc18543eab20b763f9a315ab1a44240acAndy McFadden sst.all = cookie; 77734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (sst.parts.topIndex > pRef->segmentState.parts.topIndex) { 78734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGE("Attempt to expand table with segment pop (%d to %d)\n", 79734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->segmentState.parts.topIndex, sst.parts.topIndex); 80734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return false; 81734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 82734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (sst.parts.numHoles >= sst.parts.topIndex) { 83734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGE("Absurd numHoles in cookie (%d bi=%d)\n", 84734155efc18543eab20b763f9a315ab1a44240acAndy McFadden sst.parts.numHoles, sst.parts.topIndex); 85734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return false; 86734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 87734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 885d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden LOGV("IRT %p[%d]: pop, top=%d holes=%d\n", 895d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden pRef, pRef->kind, sst.parts.topIndex, sst.parts.numHoles); 90734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 91734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return true; 92734155efc18543eab20b763f9a315ab1a44240acAndy McFadden} 93734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 94734155efc18543eab20b763f9a315ab1a44240acAndy McFadden/* 95734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Make sure that the entry at "idx" is correctly paired with "iref". 96734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 97734155efc18543eab20b763f9a315ab1a44240acAndy McFaddenstatic bool checkEntry(IndirectRefTable* pRef, IndirectRef iref, int idx) 98734155efc18543eab20b763f9a315ab1a44240acAndy McFadden{ 99734155efc18543eab20b763f9a315ab1a44240acAndy McFadden Object* obj = pRef->table[idx]; 1005d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden IndirectRef checkRef = dvmObjectToIndirectRef(pRef, obj, idx, pRef->kind); 101734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (checkRef != iref) { 1025d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden LOGW("IRT %p[%d]: iref mismatch (req=%p vs cur=%p)\n", 1035d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden pRef, pRef->kind, iref, checkRef); 104734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return false; 105734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 106734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return true; 107734155efc18543eab20b763f9a315ab1a44240acAndy McFadden} 108734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 109734155efc18543eab20b763f9a315ab1a44240acAndy McFadden/* 1105d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden * Update extended debug info when an entry is added. 1115d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden * 1125d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden * We advance the serial number, invalidating any outstanding references to 1135d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden * this slot. 1145d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden */ 1155d599603ea3d759aabe9a6b274c11b76191d1792Andy McFaddenstatic inline void updateSlotAdd(IndirectRefTable* pRef, Object* obj, int slot) 1165d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden{ 1175d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden if (pRef->slotData != NULL) { 1185d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden IndirectRefSlot* pSlot = &pRef->slotData[slot]; 1195d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden pSlot->serial++; 1205d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden //LOGI("+++ add [%d] slot %d (%p->%p), serial=%d\n", 1215d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden // pRef->kind, slot, obj, iref, pSlot->serial); 1225d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden pSlot->previous[pSlot->serial % kIRTPrevCount] = obj; 1235d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden } 1245d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden} 1255d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden 1265d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden/* 1275d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden * Update extended debug info when an entry is removed. 1285d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden */ 1295d599603ea3d759aabe9a6b274c11b76191d1792Andy McFaddenstatic inline void updateSlotRemove(IndirectRefTable* pRef, int slot) 1305d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden{ 1315d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden if (pRef->slotData != NULL) { 1325d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden IndirectRefSlot* pSlot = &pRef->slotData[slot]; 1335d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden //LOGI("+++ remove [%d] slot %d, serial now %d\n", 1345d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden // pRef->kind, slot, pSlot->serial); 1355d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden } 1365d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden} 1375d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden 1385d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden/* 139734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Add "obj" to "pRef". 140734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 141734155efc18543eab20b763f9a315ab1a44240acAndy McFaddenIndirectRef dvmAddToIndirectRefTable(IndirectRefTable* pRef, u4 cookie, 142734155efc18543eab20b763f9a315ab1a44240acAndy McFadden Object* obj) 143734155efc18543eab20b763f9a315ab1a44240acAndy McFadden{ 144734155efc18543eab20b763f9a315ab1a44240acAndy McFadden IRTSegmentState prevState; 145734155efc18543eab20b763f9a315ab1a44240acAndy McFadden prevState.all = cookie; 146734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int topIndex = pRef->segmentState.parts.topIndex; 147734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int bottomIndex = prevState.parts.topIndex; 148734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 149734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(obj != NULL); 150734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(dvmIsValidObject(obj)); 151734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(pRef->table != NULL); 152734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(pRef->allocEntries <= pRef->maxEntries); 153734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(pRef->segmentState.parts.numHoles >= prevState.parts.numHoles); 154734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 155734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (topIndex == pRef->allocEntries) { 156734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* reached end of allocated space; did we hit buffer max? */ 157734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (topIndex == pRef->maxEntries) { 1580423f0e813a3807168fe5524405eb96675532097Andy McFadden LOGW("IndirectRefTable overflow (max=%d)\n", pRef->maxEntries); 159734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return NULL; 160734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 161734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 162734155efc18543eab20b763f9a315ab1a44240acAndy McFadden Object** newTable; 163734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int newSize; 164734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 165734155efc18543eab20b763f9a315ab1a44240acAndy McFadden newSize = pRef->allocEntries * 2; 166734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (newSize > pRef->maxEntries) 167734155efc18543eab20b763f9a315ab1a44240acAndy McFadden newSize = pRef->maxEntries; 168734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(newSize > pRef->allocEntries); 169734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 170734155efc18543eab20b763f9a315ab1a44240acAndy McFadden newTable = (Object**) realloc(pRef->table, newSize * sizeof(Object*)); 171734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (newTable == NULL) { 1720423f0e813a3807168fe5524405eb96675532097Andy McFadden LOGE("Unable to expand iref table (from %d to %d, max=%d)\n", 1730423f0e813a3807168fe5524405eb96675532097Andy McFadden pRef->allocEntries, newSize, pRef->maxEntries); 174734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return false; 175734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 1760423f0e813a3807168fe5524405eb96675532097Andy McFadden LOGI("Growing ireftab %p from %d to %d (max=%d)\n", 1770423f0e813a3807168fe5524405eb96675532097Andy McFadden pRef, pRef->allocEntries, newSize, pRef->maxEntries); 178734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 179734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* update entries; adjust "nextEntry" in case memory moved */ 180734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->table = newTable; 181734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->allocEntries = newSize; 182734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 183734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 184734155efc18543eab20b763f9a315ab1a44240acAndy McFadden IndirectRef result; 185734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 186734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* 187734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * We know there's enough room in the table. Now we just need to find 188734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * the right spot. If there's a hole, find it and fill it; otherwise, 189734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * add to the end of the list. 190734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 191734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int numHoles = pRef->segmentState.parts.numHoles - prevState.parts.numHoles; 192734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (numHoles > 0) { 193734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(topIndex > 1); 194734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* find the first hole; likely to be near the end of the list */ 195734155efc18543eab20b763f9a315ab1a44240acAndy McFadden Object** pScan = &pRef->table[topIndex - 1]; 196734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(*pScan != NULL); 197734155efc18543eab20b763f9a315ab1a44240acAndy McFadden while (*--pScan != NULL) { 198734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(pScan >= pRef->table + bottomIndex); 199734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 2005d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden updateSlotAdd(pRef, obj, pScan - pRef->table); 2015d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden result = dvmObjectToIndirectRef(pRef, obj, pScan - pRef->table, 2025d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden pRef->kind); 203734155efc18543eab20b763f9a315ab1a44240acAndy McFadden *pScan = obj; 204734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->segmentState.parts.numHoles--; 205734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } else { 206734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* add to the end */ 2075d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden updateSlotAdd(pRef, obj, topIndex); 2085d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden result = dvmObjectToIndirectRef(pRef, obj, topIndex, pRef->kind); 209734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->table[topIndex++] = obj; 210734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->segmentState.parts.topIndex = topIndex; 211734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 212734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 213734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(result != NULL); 214734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return result; 215734155efc18543eab20b763f9a315ab1a44240acAndy McFadden} 216734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 217734155efc18543eab20b763f9a315ab1a44240acAndy McFadden/* 218734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Verify that the indirect table lookup is valid. 219734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * 220734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Returns "false" if something looks bad. 221734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 222734155efc18543eab20b763f9a315ab1a44240acAndy McFaddenbool dvmGetFromIndirectRefTableCheck(IndirectRefTable* pRef, IndirectRef iref) 223734155efc18543eab20b763f9a315ab1a44240acAndy McFadden{ 224ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden if (dvmGetIndirectRefType(iref) == kIndirectKindInvalid) { 225ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden LOGW("Invalid indirect reference 0x%08x\n", (u4) iref); 226ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden return false; 227ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden } 228ab00d455ea67fbf4090567bb09ead8017896ea61Andy McFadden 229734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int topIndex = pRef->segmentState.parts.topIndex; 230734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int idx = dvmIndirectRefToIndex(iref); 231734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 232734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (iref == NULL) { 233734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGI("--- lookup on NULL iref\n"); 234734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return false; 235734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 236734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (idx >= topIndex) { 237734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* bad -- stale reference? */ 238734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGI("Attempt to access invalid index %d (top=%d)\n", 239734155efc18543eab20b763f9a315ab1a44240acAndy McFadden idx, topIndex); 240734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return false; 241734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 242734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 243734155efc18543eab20b763f9a315ab1a44240acAndy McFadden Object* obj = pRef->table[idx]; 244734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (obj == NULL) { 245734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGI("Attempt to read from hole, iref=%p\n", iref); 246734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return false; 247734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 248734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (!checkEntry(pRef, iref, idx)) 249734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return false; 250734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 251734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return true; 252734155efc18543eab20b763f9a315ab1a44240acAndy McFadden} 253734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 254734155efc18543eab20b763f9a315ab1a44240acAndy McFadden/* 255734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Remove "obj" from "pRef". We extract the table offset bits from "iref" 256734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * and zap the corresponding entry, leaving a hole if it's not at the top. 257734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * 258734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * If the entry is not between the current top index and the bottom index 259734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * specified by the cookie, we don't remove anything. This is the behavior 260734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * required by JNI's DeleteLocalRef function. 261734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * 2625d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden * Note this is NOT called when a local frame is popped. This is only used 2635d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden * for explict single removals. 2645d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden * 265734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Returns "false" if nothing was removed. 266734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 267734155efc18543eab20b763f9a315ab1a44240acAndy McFaddenbool dvmRemoveFromIndirectRefTable(IndirectRefTable* pRef, u4 cookie, 268734155efc18543eab20b763f9a315ab1a44240acAndy McFadden IndirectRef iref) 269734155efc18543eab20b763f9a315ab1a44240acAndy McFadden{ 270734155efc18543eab20b763f9a315ab1a44240acAndy McFadden IRTSegmentState prevState; 271734155efc18543eab20b763f9a315ab1a44240acAndy McFadden prevState.all = cookie; 272734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int topIndex = pRef->segmentState.parts.topIndex; 273734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int bottomIndex = prevState.parts.topIndex; 274734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 275734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(pRef->table != NULL); 276734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(pRef->allocEntries <= pRef->maxEntries); 277734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(pRef->segmentState.parts.numHoles >= prevState.parts.numHoles); 278734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 279734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int idx = dvmIndirectRefToIndex(iref); 280734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (idx < bottomIndex) { 281734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* wrong segment */ 282734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGV("Attempt to remove index outside index area (%d vs %d-%d)\n", 283734155efc18543eab20b763f9a315ab1a44240acAndy McFadden idx, bottomIndex, topIndex); 284734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return false; 285734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 286734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (idx >= topIndex) { 287734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* bad -- stale reference? */ 288734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGI("Attempt to remove invalid index %d (bottom=%d top=%d)\n", 289734155efc18543eab20b763f9a315ab1a44240acAndy McFadden idx, bottomIndex, topIndex); 290734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return false; 291734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 292734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 293734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (idx == topIndex-1) { 294734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* 295734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Top-most entry. Scan up and consume holes. No need to NULL 296734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * out the entry, since the test vs. topIndex will catch it. 297734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 298734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (!checkEntry(pRef, iref, idx)) 299734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return false; 3005d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden updateSlotRemove(pRef, idx); 301734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 302734155efc18543eab20b763f9a315ab1a44240acAndy McFadden#ifndef NDEBUG 303734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->table[idx] = (IndirectRef) 0xd3d3d3d3; 304734155efc18543eab20b763f9a315ab1a44240acAndy McFadden#endif 305734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 306734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int numHoles = 307734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->segmentState.parts.numHoles - prevState.parts.numHoles; 308734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (numHoles != 0) { 309734155efc18543eab20b763f9a315ab1a44240acAndy McFadden while (--topIndex > bottomIndex && numHoles != 0) { 310734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGV("+++ checking for hole at %d (cookie=0x%08x) val=%p\n", 311734155efc18543eab20b763f9a315ab1a44240acAndy McFadden topIndex-1, cookie, pRef->table[topIndex-1]); 312734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (pRef->table[topIndex-1] != NULL) 313734155efc18543eab20b763f9a315ab1a44240acAndy McFadden break; 314734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGV("+++ ate hole at %d\n", topIndex-1); 315734155efc18543eab20b763f9a315ab1a44240acAndy McFadden numHoles--; 316734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 317734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->segmentState.parts.numHoles = 318734155efc18543eab20b763f9a315ab1a44240acAndy McFadden numHoles + prevState.parts.numHoles; 319734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->segmentState.parts.topIndex = topIndex; 320734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } else { 321734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->segmentState.parts.topIndex = topIndex-1; 322734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGV("+++ ate last entry %d\n", topIndex-1); 323734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 324734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } else { 325734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* 326734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Not the top-most entry. This creates a hole. We NULL out the 327734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * entry to prevent somebody from deleting it twice and screwing up 328734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * the hole count. 329734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 330734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (pRef->table[idx] == NULL) { 331734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGV("--- WEIRD: removing null entry %d\n", idx); 332734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return false; 333734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 334734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (!checkEntry(pRef, iref, idx)) 335734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return false; 3365d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden updateSlotRemove(pRef, idx); 337734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 338734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->table[idx] = NULL; 339734155efc18543eab20b763f9a315ab1a44240acAndy McFadden pRef->segmentState.parts.numHoles++; 340734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGV("+++ left hole at %d, holes=%d\n", 341734155efc18543eab20b763f9a315ab1a44240acAndy McFadden idx, pRef->segmentState.parts.numHoles); 342734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 343734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 344734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return true; 345734155efc18543eab20b763f9a315ab1a44240acAndy McFadden} 346734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 347734155efc18543eab20b763f9a315ab1a44240acAndy McFadden/* 348734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * This is a qsort() callback. We sort Object* by class, allocation size, 349734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * and then by the Object* itself. 350734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 351734155efc18543eab20b763f9a315ab1a44240acAndy McFaddenstatic int compareObject(const void* vobj1, const void* vobj2) 352734155efc18543eab20b763f9a315ab1a44240acAndy McFadden{ 353734155efc18543eab20b763f9a315ab1a44240acAndy McFadden Object* obj1 = *((Object**) vobj1); 354734155efc18543eab20b763f9a315ab1a44240acAndy McFadden Object* obj2 = *((Object**) vobj2); 355734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 356734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* ensure null references appear at the end */ 357734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (obj1 == NULL) { 358734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (obj2 == NULL) { 359734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return 0; 360734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } else { 361734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return 1; 362734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 363734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } else if (obj2 == NULL) { 364734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return -1; 365734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 366734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 367734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (obj1->clazz != obj2->clazz) { 368734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return (u1*)obj1->clazz - (u1*)obj2->clazz; 369734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } else { 370734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int size1 = dvmObjectSizeInHeap(obj1); 371734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int size2 = dvmObjectSizeInHeap(obj2); 372734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (size1 != size2) { 373734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return size1 - size2; 374734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } else { 375734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return (u1*)obj1 - (u1*)obj2; 376734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 377734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 378734155efc18543eab20b763f9a315ab1a44240acAndy McFadden} 379734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 380734155efc18543eab20b763f9a315ab1a44240acAndy McFadden/* 381734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Log an object with some additional info. 382734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * 383734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Pass in the number of additional elements that are identical to or 384734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * equivalent to the original. 385734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 386734155efc18543eab20b763f9a315ab1a44240acAndy McFaddenstatic void logObject(Object* obj, int size, int identical, int equiv) 387734155efc18543eab20b763f9a315ab1a44240acAndy McFadden{ 388734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (obj == NULL) { 389734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGW(" NULL reference (count=%d)\n", equiv); 390734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return; 391734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 392734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 393734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (identical + equiv != 0) { 394734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGW("%5d of %s %dB (%d unique)\n", identical + equiv +1, 395734155efc18543eab20b763f9a315ab1a44240acAndy McFadden obj->clazz->descriptor, size, equiv +1); 396734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } else { 397734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGW("%5d of %s %dB\n", identical + equiv +1, 398734155efc18543eab20b763f9a315ab1a44240acAndy McFadden obj->clazz->descriptor, size); 399734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 400734155efc18543eab20b763f9a315ab1a44240acAndy McFadden} 401734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 402734155efc18543eab20b763f9a315ab1a44240acAndy McFadden/* 403734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Dump the contents of a IndirectRefTable to the log. 404734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 405734155efc18543eab20b763f9a315ab1a44240acAndy McFaddenvoid dvmDumpIndirectRefTable(const IndirectRefTable* pRef, const char* descr) 406734155efc18543eab20b763f9a315ab1a44240acAndy McFadden{ 407734155efc18543eab20b763f9a315ab1a44240acAndy McFadden const int kLast = 10; 408734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int count = dvmIndirectRefTableEntries(pRef); 409734155efc18543eab20b763f9a315ab1a44240acAndy McFadden Object** refs; 410734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int i; 411734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 412734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (count == 0) { 413734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGW("Reference table has no entries\n"); 414734155efc18543eab20b763f9a315ab1a44240acAndy McFadden return; 415734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 416734155efc18543eab20b763f9a315ab1a44240acAndy McFadden assert(count > 0); 417734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 418734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* 419734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Dump the most recent N entries. If there are holes, we will show 420734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * fewer than N. 421734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 422734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGW("Last %d entries in %s reference table:\n", kLast, descr); 423734155efc18543eab20b763f9a315ab1a44240acAndy McFadden refs = pRef->table; // use unsorted list 424734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int size; 425734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int start = count - kLast; 426734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (start < 0) 427734155efc18543eab20b763f9a315ab1a44240acAndy McFadden start = 0; 428734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 429734155efc18543eab20b763f9a315ab1a44240acAndy McFadden for (i = start; i < count; i++) { 430734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (refs[i] == NULL) 431734155efc18543eab20b763f9a315ab1a44240acAndy McFadden continue; 432734155efc18543eab20b763f9a315ab1a44240acAndy McFadden size = dvmObjectSizeInHeap(refs[i]); 433734155efc18543eab20b763f9a315ab1a44240acAndy McFadden Object* ref = refs[i]; 434734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (ref->clazz == gDvm.classJavaLangClass) { 435734155efc18543eab20b763f9a315ab1a44240acAndy McFadden ClassObject* clazz = (ClassObject*) ref; 436734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGW("%5d: %p cls=%s '%s' (%d bytes)\n", i, ref, 437734155efc18543eab20b763f9a315ab1a44240acAndy McFadden (refs[i] == NULL) ? "-" : ref->clazz->descriptor, 438734155efc18543eab20b763f9a315ab1a44240acAndy McFadden clazz->descriptor, size); 439734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } else { 440734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGW("%5d: %p cls=%s (%d bytes)\n", i, ref, 441734155efc18543eab20b763f9a315ab1a44240acAndy McFadden (refs[i] == NULL) ? "-" : ref->clazz->descriptor, size); 442734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 443734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 444734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 445734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* 446734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Make a copy of the table, and sort it. 447734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * 448734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * The NULL "holes" wind up at the end, so we can strip them off easily. 449734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 450734155efc18543eab20b763f9a315ab1a44240acAndy McFadden Object** tableCopy = (Object**)malloc(sizeof(Object*) * count); 451734155efc18543eab20b763f9a315ab1a44240acAndy McFadden memcpy(tableCopy, pRef->table, sizeof(Object*) * count); 452734155efc18543eab20b763f9a315ab1a44240acAndy McFadden qsort(tableCopy, count, sizeof(Object*), compareObject); 453734155efc18543eab20b763f9a315ab1a44240acAndy McFadden refs = tableCopy; // use sorted list 454734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 4555d599603ea3d759aabe9a6b274c11b76191d1792Andy McFadden if (false) { 456734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int q; 457734155efc18543eab20b763f9a315ab1a44240acAndy McFadden for (q = 0; q < count; q++) 458734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGI("%d %p\n", q, refs[q]); 459734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 460734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 461734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int holes = 0; 462734155efc18543eab20b763f9a315ab1a44240acAndy McFadden while (refs[count-1] == NULL) { 463734155efc18543eab20b763f9a315ab1a44240acAndy McFadden count--; 464734155efc18543eab20b763f9a315ab1a44240acAndy McFadden holes++; 465734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 466734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 467734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* 468734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * Dump uniquified table summary. While we're at it, generate a 469734155efc18543eab20b763f9a315ab1a44240acAndy McFadden * cumulative total amount of pinned memory based on the unique entries. 470734155efc18543eab20b763f9a315ab1a44240acAndy McFadden */ 471734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGW("%s reference table summary (%d entries / %d holes):\n", 472734155efc18543eab20b763f9a315ab1a44240acAndy McFadden descr, count, holes); 473734155efc18543eab20b763f9a315ab1a44240acAndy McFadden int equiv, identical, total; 474734155efc18543eab20b763f9a315ab1a44240acAndy McFadden total = equiv = identical = 0; 475734155efc18543eab20b763f9a315ab1a44240acAndy McFadden for (i = 1; i < count; i++) { 476734155efc18543eab20b763f9a315ab1a44240acAndy McFadden size = dvmObjectSizeInHeap(refs[i-1]); 477734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 478734155efc18543eab20b763f9a315ab1a44240acAndy McFadden if (refs[i] == refs[i-1]) { 479734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* same reference, added more than once */ 480734155efc18543eab20b763f9a315ab1a44240acAndy McFadden identical++; 481734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } else if (refs[i]->clazz == refs[i-1]->clazz && 482734155efc18543eab20b763f9a315ab1a44240acAndy McFadden (int) dvmObjectSizeInHeap(refs[i]) == size) 483734155efc18543eab20b763f9a315ab1a44240acAndy McFadden { 484734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* same class / size, different object */ 485734155efc18543eab20b763f9a315ab1a44240acAndy McFadden total += size; 486734155efc18543eab20b763f9a315ab1a44240acAndy McFadden equiv++; 487734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } else { 488734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* different class */ 489734155efc18543eab20b763f9a315ab1a44240acAndy McFadden total += size; 490734155efc18543eab20b763f9a315ab1a44240acAndy McFadden logObject(refs[i-1], size, identical, equiv); 491734155efc18543eab20b763f9a315ab1a44240acAndy McFadden equiv = identical = 0; 492734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 493734155efc18543eab20b763f9a315ab1a44240acAndy McFadden } 494734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 495734155efc18543eab20b763f9a315ab1a44240acAndy McFadden /* handle the last entry (everything above outputs refs[i-1]) */ 496734155efc18543eab20b763f9a315ab1a44240acAndy McFadden size = (refs[count-1] == NULL) ? 0 : dvmObjectSizeInHeap(refs[count-1]); 497734155efc18543eab20b763f9a315ab1a44240acAndy McFadden total += size; 498734155efc18543eab20b763f9a315ab1a44240acAndy McFadden logObject(refs[count-1], size, identical, equiv); 499734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 500734155efc18543eab20b763f9a315ab1a44240acAndy McFadden LOGW("Memory held directly by native code is %d bytes\n", total); 501734155efc18543eab20b763f9a315ab1a44240acAndy McFadden free(tableCopy); 502734155efc18543eab20b763f9a315ab1a44240acAndy McFadden} 503734155efc18543eab20b763f9a315ab1a44240acAndy McFadden 504