Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2009 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | /* |
| 18 | * Indirect reference table management. |
| 19 | */ |
| 20 | #include "Dalvik.h" |
| 21 | |
Elliott Hughes | 24c57f1 | 2011-06-29 11:10:21 -0700 | [diff] [blame] | 22 | static void abortMaybe() { |
| 23 | // If CheckJNI is on, it'll give a more detailed error before aborting. |
| 24 | // Otherwise, we want to abort rather than hand back a bad reference. |
| 25 | if (!gDvmJni.useCheckJni) { |
| 26 | dvmAbort(); |
| 27 | } |
| 28 | } |
| 29 | |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 30 | bool IndirectRefTable::init(size_t initialCount, |
| 31 | size_t maxCount, IndirectRefKind desiredKind) |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 32 | { |
| 33 | assert(initialCount > 0); |
| 34 | assert(initialCount <= maxCount); |
Carl Shapiro | e4c3b5e | 2011-03-08 13:44:51 -0800 | [diff] [blame] | 35 | assert(kind != kIndirectKindInvalid); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 36 | |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 37 | table = (Object**) malloc(initialCount * sizeof(Object*)); |
| 38 | if (table == NULL) { |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 39 | return false; |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 40 | } |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 41 | #ifndef NDEBUG |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 42 | memset(table, 0xd1, initialCount * sizeof(Object*)); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 43 | #endif |
Andy McFadden | 5d59960 | 2009-08-31 16:39:23 -0700 | [diff] [blame] | 44 | |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 45 | slotData = |
Andy McFadden | 5d59960 | 2009-08-31 16:39:23 -0700 | [diff] [blame] | 46 | (IndirectRefSlot*) calloc(maxCount, sizeof(IndirectRefSlot)); |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 47 | if (slotData == NULL) { |
Andy McFadden | 5d59960 | 2009-08-31 16:39:23 -0700 | [diff] [blame] | 48 | return false; |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 49 | } |
Andy McFadden | 5d59960 | 2009-08-31 16:39:23 -0700 | [diff] [blame] | 50 | |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 51 | segmentState.all = IRT_FIRST_SEGMENT; |
| 52 | allocEntries = initialCount; |
| 53 | maxEntries = maxCount; |
| 54 | kind = desiredKind; |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 55 | |
| 56 | return true; |
| 57 | } |
| 58 | |
| 59 | /* |
| 60 | * Clears out the contents of a IndirectRefTable, freeing allocated storage. |
| 61 | */ |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 62 | void IndirectRefTable::destroy() |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 63 | { |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 64 | free(table); |
| 65 | free(slotData); |
| 66 | table = NULL; |
| 67 | allocEntries = maxEntries = -1; |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 68 | } |
| 69 | |
| 70 | /* |
| 71 | * Make sure that the entry at "idx" is correctly paired with "iref". |
| 72 | */ |
Elliott Hughes | ddbd6f4 | 2011-07-06 14:22:18 -0700 | [diff] [blame^] | 73 | bool IndirectRefTable::checkEntry(const char* what, IndirectRef iref, int idx) const |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 74 | { |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 75 | Object* obj = table[idx]; |
| 76 | IndirectRef checkRef = toIndirectRef(obj, idx); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 77 | if (checkRef != iref) { |
Elliott Hughes | ddbd6f4 | 2011-07-06 14:22:18 -0700 | [diff] [blame^] | 78 | if (indirectRefKind(iref) != kIndirectKindWeakGlobal) { |
| 79 | LOGE("JNI ERROR (app bug): attempt to %s stale %s reference (req=%p vs cur=%p; table=%p)", |
| 80 | what, indirectRefKindToString(kind), iref, checkRef, this); |
| 81 | abortMaybe(); |
| 82 | } |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 83 | return false; |
| 84 | } |
| 85 | return true; |
| 86 | } |
| 87 | |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 88 | IndirectRef IndirectRefTable::add(u4 cookie, Object* obj) |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 89 | { |
| 90 | IRTSegmentState prevState; |
| 91 | prevState.all = cookie; |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 92 | size_t topIndex = segmentState.parts.topIndex; |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 93 | |
| 94 | assert(obj != NULL); |
| 95 | assert(dvmIsValidObject(obj)); |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 96 | assert(table != NULL); |
| 97 | assert(allocEntries <= maxEntries); |
| 98 | assert(segmentState.parts.numHoles >= prevState.parts.numHoles); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 99 | |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 100 | if (topIndex == allocEntries) { |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 101 | /* reached end of allocated space; did we hit buffer max? */ |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 102 | if (topIndex == maxEntries) { |
Elliott Hughes | 24c57f1 | 2011-06-29 11:10:21 -0700 | [diff] [blame] | 103 | LOGE("JNI ERROR (app bug): %s reference table overflow (max=%d)", |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 104 | indirectRefKindToString(kind), maxEntries); |
Elliott Hughes | 24c57f1 | 2011-06-29 11:10:21 -0700 | [diff] [blame] | 105 | dump(indirectRefKindToString(kind)); |
| 106 | dvmAbort(); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 107 | } |
| 108 | |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 109 | size_t newSize = allocEntries * 2; |
| 110 | if (newSize > maxEntries) { |
| 111 | newSize = maxEntries; |
| 112 | } |
| 113 | assert(newSize > allocEntries); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 114 | |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 115 | Object** newTable = (Object**) realloc(table, newSize * sizeof(Object*)); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 116 | if (newTable == NULL) { |
Elliott Hughes | 24c57f1 | 2011-06-29 11:10:21 -0700 | [diff] [blame] | 117 | LOGE("JNI ERROR (app bug): unable to expand %s reference table (from %d to %d, max=%d)", |
| 118 | indirectRefKindToString(kind), |
| 119 | allocEntries, newSize, maxEntries); |
| 120 | dump(indirectRefKindToString(kind)); |
| 121 | dvmAbort(); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 122 | } |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 123 | |
| 124 | /* update entries; adjust "nextEntry" in case memory moved */ |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 125 | table = newTable; |
| 126 | allocEntries = newSize; |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 127 | } |
| 128 | |
| 129 | IndirectRef result; |
| 130 | |
| 131 | /* |
| 132 | * We know there's enough room in the table. Now we just need to find |
| 133 | * the right spot. If there's a hole, find it and fill it; otherwise, |
| 134 | * add to the end of the list. |
| 135 | */ |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 136 | int numHoles = segmentState.parts.numHoles - prevState.parts.numHoles; |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 137 | if (numHoles > 0) { |
| 138 | assert(topIndex > 1); |
| 139 | /* find the first hole; likely to be near the end of the list */ |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 140 | Object** pScan = &table[topIndex - 1]; |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 141 | assert(*pScan != NULL); |
| 142 | while (*--pScan != NULL) { |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 143 | assert(pScan >= table + prevState.parts.topIndex); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 144 | } |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 145 | updateSlotAdd(obj, pScan - table); |
| 146 | result = toIndirectRef(obj, pScan - table); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 147 | *pScan = obj; |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 148 | segmentState.parts.numHoles--; |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 149 | } else { |
| 150 | /* add to the end */ |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 151 | updateSlotAdd(obj, topIndex); |
| 152 | result = toIndirectRef(obj, topIndex); |
| 153 | table[topIndex++] = obj; |
| 154 | segmentState.parts.topIndex = topIndex; |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 155 | } |
| 156 | |
| 157 | assert(result != NULL); |
| 158 | return result; |
| 159 | } |
| 160 | |
| 161 | /* |
| 162 | * Verify that the indirect table lookup is valid. |
| 163 | * |
| 164 | * Returns "false" if something looks bad. |
| 165 | */ |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 166 | bool IndirectRefTable::getChecked(IndirectRef iref) const |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 167 | { |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 168 | if (iref == NULL) { |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 169 | LOGW("Attempt to look up NULL %s reference", |
| 170 | indirectRefKindToString(kind)); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 171 | return false; |
| 172 | } |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 173 | if (indirectRefKind(iref) == kIndirectKindInvalid) { |
Elliott Hughes | 24c57f1 | 2011-06-29 11:10:21 -0700 | [diff] [blame] | 174 | LOGE("JNI ERROR (app bug): invalid %s reference (%p)", |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 175 | indirectRefKindToString(kind), iref); |
Elliott Hughes | 24c57f1 | 2011-06-29 11:10:21 -0700 | [diff] [blame] | 176 | abortMaybe(); |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 177 | return false; |
| 178 | } |
| 179 | |
| 180 | int topIndex = segmentState.parts.topIndex; |
| 181 | int idx = extractIndex(iref); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 182 | if (idx >= topIndex) { |
| 183 | /* bad -- stale reference? */ |
Elliott Hughes | 24c57f1 | 2011-06-29 11:10:21 -0700 | [diff] [blame] | 184 | LOGE("JNI ERROR (app bug): accessed stale %s reference at index %d (top=%d)", |
| 185 | indirectRefKindToString(kind), idx, topIndex); |
| 186 | abortMaybe(); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 187 | return false; |
| 188 | } |
| 189 | |
Elliott Hughes | ddbd6f4 | 2011-07-06 14:22:18 -0700 | [diff] [blame^] | 190 | if (!checkEntry("use", iref, idx)) { |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 191 | return false; |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 192 | } |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 193 | |
| 194 | return true; |
| 195 | } |
| 196 | |
| 197 | /* |
| 198 | * Remove "obj" from "pRef". We extract the table offset bits from "iref" |
| 199 | * and zap the corresponding entry, leaving a hole if it's not at the top. |
| 200 | * |
| 201 | * If the entry is not between the current top index and the bottom index |
| 202 | * specified by the cookie, we don't remove anything. This is the behavior |
| 203 | * required by JNI's DeleteLocalRef function. |
| 204 | * |
Andy McFadden | 5d59960 | 2009-08-31 16:39:23 -0700 | [diff] [blame] | 205 | * Note this is NOT called when a local frame is popped. This is only used |
Elliott Hughes | ddbd6f4 | 2011-07-06 14:22:18 -0700 | [diff] [blame^] | 206 | * for explicit single removals. |
Andy McFadden | 5d59960 | 2009-08-31 16:39:23 -0700 | [diff] [blame] | 207 | * |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 208 | * Returns "false" if nothing was removed. |
| 209 | */ |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 210 | bool IndirectRefTable::remove(u4 cookie, IndirectRef iref) |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 211 | { |
| 212 | IRTSegmentState prevState; |
| 213 | prevState.all = cookie; |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 214 | int topIndex = segmentState.parts.topIndex; |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 215 | int bottomIndex = prevState.parts.topIndex; |
| 216 | |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 217 | assert(table != NULL); |
| 218 | assert(allocEntries <= maxEntries); |
| 219 | assert(segmentState.parts.numHoles >= prevState.parts.numHoles); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 220 | |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 221 | int idx = extractIndex(iref); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 222 | if (idx < bottomIndex) { |
| 223 | /* wrong segment */ |
Dan Bornstein | 60fc806 | 2011-05-26 10:11:58 -0700 | [diff] [blame] | 224 | LOGV("Attempt to remove index outside index area (%d vs %d-%d)", |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 225 | idx, bottomIndex, topIndex); |
| 226 | return false; |
| 227 | } |
| 228 | if (idx >= topIndex) { |
| 229 | /* bad -- stale reference? */ |
Dan Bornstein | 60fc806 | 2011-05-26 10:11:58 -0700 | [diff] [blame] | 230 | LOGD("Attempt to remove invalid index %d (bottom=%d top=%d)", |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 231 | idx, bottomIndex, topIndex); |
| 232 | return false; |
| 233 | } |
| 234 | |
| 235 | if (idx == topIndex-1) { |
| 236 | /* |
| 237 | * Top-most entry. Scan up and consume holes. No need to NULL |
| 238 | * out the entry, since the test vs. topIndex will catch it. |
| 239 | */ |
Elliott Hughes | ddbd6f4 | 2011-07-06 14:22:18 -0700 | [diff] [blame^] | 240 | if (!checkEntry("remove", iref, idx)) { |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 241 | return false; |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 242 | } |
| 243 | updateSlotRemove(idx); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 244 | |
| 245 | #ifndef NDEBUG |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 246 | table[idx] = (Object*)0xd3d3d3d3; |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 247 | #endif |
| 248 | |
| 249 | int numHoles = |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 250 | segmentState.parts.numHoles - prevState.parts.numHoles; |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 251 | if (numHoles != 0) { |
| 252 | while (--topIndex > bottomIndex && numHoles != 0) { |
Dan Bornstein | 60fc806 | 2011-05-26 10:11:58 -0700 | [diff] [blame] | 253 | LOGV("+++ checking for hole at %d (cookie=0x%08x) val=%p", |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 254 | topIndex-1, cookie, table[topIndex-1]); |
| 255 | if (table[topIndex-1] != NULL) |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 256 | break; |
Dan Bornstein | 60fc806 | 2011-05-26 10:11:58 -0700 | [diff] [blame] | 257 | LOGV("+++ ate hole at %d", topIndex-1); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 258 | numHoles--; |
| 259 | } |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 260 | segmentState.parts.numHoles = |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 261 | numHoles + prevState.parts.numHoles; |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 262 | segmentState.parts.topIndex = topIndex; |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 263 | } else { |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 264 | segmentState.parts.topIndex = topIndex-1; |
Dan Bornstein | 60fc806 | 2011-05-26 10:11:58 -0700 | [diff] [blame] | 265 | LOGV("+++ ate last entry %d", topIndex-1); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 266 | } |
| 267 | } else { |
| 268 | /* |
| 269 | * Not the top-most entry. This creates a hole. We NULL out the |
| 270 | * entry to prevent somebody from deleting it twice and screwing up |
| 271 | * the hole count. |
| 272 | */ |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 273 | if (table[idx] == NULL) { |
Dan Bornstein | 60fc806 | 2011-05-26 10:11:58 -0700 | [diff] [blame] | 274 | LOGV("--- WEIRD: removing null entry %d", idx); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 275 | return false; |
| 276 | } |
Elliott Hughes | ddbd6f4 | 2011-07-06 14:22:18 -0700 | [diff] [blame^] | 277 | if (!checkEntry("remove", iref, idx)) { |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 278 | return false; |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 279 | } |
| 280 | updateSlotRemove(idx); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 281 | |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 282 | table[idx] = NULL; |
| 283 | segmentState.parts.numHoles++; |
Dan Bornstein | 60fc806 | 2011-05-26 10:11:58 -0700 | [diff] [blame] | 284 | LOGV("+++ left hole at %d, holes=%d", |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 285 | idx, segmentState.parts.numHoles); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 286 | } |
| 287 | |
| 288 | return true; |
| 289 | } |
| 290 | |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 291 | const char* indirectRefKindToString(IndirectRefKind kind) |
Andy McFadden | c759b9f | 2011-04-07 10:36:56 -0700 | [diff] [blame] | 292 | { |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 293 | switch (kind) { |
Andy McFadden | c759b9f | 2011-04-07 10:36:56 -0700 | [diff] [blame] | 294 | case kIndirectKindInvalid: return "invalid"; |
| 295 | case kIndirectKindLocal: return "local"; |
| 296 | case kIndirectKindGlobal: return "global"; |
| 297 | case kIndirectKindWeakGlobal: return "weak global"; |
| 298 | default: return "UNKNOWN"; |
| 299 | } |
| 300 | } |
| 301 | |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 302 | void IndirectRefTable::dump(const char* descr) const |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 303 | { |
Elliott Hughes | ce09683 | 2011-06-20 17:50:41 -0700 | [diff] [blame] | 304 | dvmDumpReferenceTableContents(table, capacity(), descr); |
Andy McFadden | 734155e | 2009-07-16 18:11:22 -0700 | [diff] [blame] | 305 | } |