/* * Make sure that the entry at "idx" is correctly paired with "iref". */ bool IndirectRefTable::checkEntry(const char* what, IndirectRef iref, int idx) const { Object* obj = table_[idx]; IndirectRef checkRef = toIndirectRef(obj, idx); if (checkRef != iref) { LOGE("JNI ERROR (app bug): attempt to %s stale %s reference %p (should be %p)", what, indirectRefKindToString(kind_), iref, checkRef); abortMaybe(); return false; } return true; }
/* *breif:添加一个新的条目.重新调整表大小. *param[cookie]: *param[obj]:要添加的条目. */ IndirectRef IndirectRefTable::add(u4 cookie, Object* obj) { IRTSegmentState prevState; prevState.all = cookie; size_t topIndex = segmentState.parts.topIndex; assert(obj != NULL); assert(dvmIsHeapAddress(obj)); assert(table_ != NULL); assert(alloc_entries_ <= max_entries_); assert(segmentState.parts.numHoles >= prevState.parts.numHoles); /* * We know there's enough room in the table. Now we just need to find * the right spot. If there's a hole, find it and fill it; otherwise, * add to the end of the list. */ IndirectRef result; IndirectRefSlot* slot; int numHoles = segmentState.parts.numHoles - prevState.parts.numHoles; if (numHoles > 0) { assert(topIndex > 1); /* find the first hole; likely to be near the end of the list, * we know the item at the topIndex is not a hole */ slot = &table_[topIndex - 1]; assert(slot->obj != NULL); while ((--slot)->obj != NULL) { assert(slot >= table_ + prevState.parts.topIndex); } segmentState.parts.numHoles--; } else { /* add to the end, grow if needed */ if (topIndex == alloc_entries_) { /* reached end of allocated space; did we hit buffer max? */ if (topIndex == max_entries_) { ALOGE("JNI ERROR (app bug): %s reference table overflow (max=%d)", indirectRefKindToString(kind_), max_entries_); return NULL; } size_t newSize = alloc_entries_ * 2; if (newSize > max_entries_) { newSize = max_entries_; } assert(newSize > alloc_entries_); IndirectRefSlot* newTable = (IndirectRefSlot*) realloc(table_, newSize * sizeof(IndirectRefSlot)); if (table_ == NULL) { ALOGE("JNI ERROR (app bug): unable to expand %s reference table " "(from %d to %d, max=%d)", indirectRefKindToString(kind_), alloc_entries_, newSize, max_entries_); return NULL; } memset(newTable + alloc_entries_, 0xd1, (newSize - alloc_entries_) * sizeof(IndirectRefSlot)); alloc_entries_ = newSize; table_ = newTable; } slot = &table_[topIndex++]; segmentState.parts.topIndex = topIndex; } slot->obj = obj; slot->serial = nextSerial(slot->serial); result = toIndirectRef(slot - table_, slot->serial, kind_); assert(result != NULL); return result; }
IndirectRef IndirectRefTable::add(u4 cookie, Object* obj) { IRTSegmentState prevState; prevState.all = cookie; size_t topIndex = segmentState.parts.topIndex; assert(obj != NULL); assert(dvmIsHeapAddress(obj)); assert(table_ != NULL); assert(alloc_entries_ <= max_entries_); assert(segmentState.parts.numHoles >= prevState.parts.numHoles); if (topIndex == alloc_entries_) { /* reached end of allocated space; did we hit buffer max? */ if (topIndex == max_entries_) { LOGE("JNI ERROR (app bug): %s reference table overflow (max=%d)", indirectRefKindToString(kind_), max_entries_); dump(indirectRefKindToString(kind_)); dvmAbort(); } size_t newSize = alloc_entries_ * 2; if (newSize > max_entries_) { newSize = max_entries_; } assert(newSize > alloc_entries_); table_ = (Object**) realloc(table_, newSize * sizeof(Object*)); slot_data_ = (IndirectRefSlot*) realloc(slot_data_, newSize * sizeof(IndirectRefSlot)); if (table_ == NULL || slot_data_ == NULL) { LOGE("JNI ERROR (app bug): unable to expand %s reference table (from %d to %d, max=%d)", indirectRefKindToString(kind_), alloc_entries_, newSize, max_entries_); dump(indirectRefKindToString(kind_)); dvmAbort(); } // Clear the newly-allocated slot_data_ elements. memset(slot_data_ + alloc_entries_, 0, (newSize - alloc_entries_) * sizeof(IndirectRefSlot)); alloc_entries_ = newSize; } /* * We know there's enough room in the table. Now we just need to find * the right spot. If there's a hole, find it and fill it; otherwise, * add to the end of the list. */ IndirectRef result; int numHoles = segmentState.parts.numHoles - prevState.parts.numHoles; if (numHoles > 0) { assert(topIndex > 1); /* find the first hole; likely to be near the end of the list */ Object** pScan = &table_[topIndex - 1]; assert(*pScan != NULL); while (*--pScan != NULL) { assert(pScan >= table_ + prevState.parts.topIndex); } updateSlotAdd(obj, pScan - table_); result = toIndirectRef(obj, pScan - table_); *pScan = obj; segmentState.parts.numHoles--; } else { /* add to the end */ updateSlotAdd(obj, topIndex); result = toIndirectRef(obj, topIndex); table_[topIndex++] = obj; segmentState.parts.topIndex = topIndex; } assert(result != NULL); return result; }