//遍历bitmap,找到垃圾对象的指针,回调相关函数
void dvmHeapBitmapSweepWalk(const HeapBitmap *liveHb, const HeapBitmap *markHb,
uintptr_t base, uintptr_t max,
BitmapSweepCallback *callback, void *callbackArg)
{
assert(liveHb != NULL);
assert(liveHb->bits != NULL);
assert(markHb != NULL);
assert(markHb->bits != NULL);
assert(liveHb->base == markHb->base);
assert(liveHb->bitsLen == markHb->bitsLen);
assert(callback != NULL);
assert(base <= max);
assert(base >= liveHb->base);
assert(max <= liveHb->max);
if (liveHb->max < liveHb->base) {
/* Easy case; both are obviously empty.
*/
return;
}
void *pointerBuf[4 * HB_BITS_PER_WORD];
void **pb = pointerBuf;
//live bits跟踪分配回收代码
size_t start = HB_OFFSET_TO_INDEX(base - liveHb->base);
size_t end = HB_OFFSET_TO_INDEX(max - liveHb->base);
unsigned long *live = liveHb->bits;
unsigned long *mark = markHb->bits;
for (size_t i = start; i <= end; i++) {
//live = 0 mark = 1 代码层已经free,但是可达,说明有引用指向该对象 garbage = 0
//live = 0 mark = 0 代码层已经free,且不可达,不视为垃圾 garbage = 0
//live = 1 mark = 0 代码层未free,但是已经不可达,视为垃圾 garbage = 1
//live = 1 mark = 1 代码层未free,且可达,该对象不可回收 garbage = 0
unsigned long garbage = live[i] & ~mark[i];
if (UNLIKELY(garbage != 0)) {
unsigned long highBit = 1 << (HB_BITS_PER_WORD - 1);
uintptr_t ptrBase = HB_INDEX_TO_OFFSET(i) + liveHb->base;
while (garbage != 0) {
int shift = CLZ(garbage);
garbage &= ~(highBit >> shift);
//pointer Buffer存放将要回收的地址
*pb++ = (void *)(ptrBase + shift * HB_OBJECT_ALIGNMENT);
}
/* Make sure that there are always enough slots available */
/* for an entire word of 1s. */
//pointer Buffer始终保留了一个word的大小
if (pb >= &pointerBuf[NELEM(pointerBuf) - HB_BITS_PER_WORD]) {
(*callback)(pb - pointerBuf, pointerBuf, callbackArg);
pb = pointerBuf;
}
}
}
if (pb > pointerBuf) {
(*callback)(pb - pointerBuf, pointerBuf, callbackArg);
}
}
static void sweepBitmapCallback(size_t numPtrs, void **ptrs, void *arg)
{
assert(arg != NULL);
SweepContext *ctx = (SweepContext *)arg;
if (ctx->isConcurrent) {
dvmLockHeap();
}
ctx->numBytes += dvmHeapSourceFreeList(numPtrs, ptrs);
ctx->numObjects += numPtrs;
if (ctx->isConcurrent) {
dvmUnlockHeap();
}
}
void dvmHeapSourceGrowForUtilization()
{
HS_BOILERPLATE();
HeapSource *hs = gHs;
Heap* heap = hs2heap(hs);
/* Use the current target utilization ratio to determine the
* ideal heap size based on the size of the live set.
* Note that only the active heap plays any part in this.
*
* Avoid letting the old heaps influence the target free size,
* because they may be full of objects that aren't actually
* in the working set. Just look at the allocated size of
* the current heap.
*/
size_t currentHeapUsed = heap->bytesAllocated;
size_t targetHeapSize = getUtilizationTarget(hs, currentHeapUsed);
/* The ideal size includes the old heaps; add overhead so that
* it can be immediately subtracted again in setIdealFootprint().
* If the target heap size would exceed the max, setIdealFootprint()
* will clamp it to a legal value.
*/
//此部分为非要不可的内存大小
size_t overhead = getSoftFootprint(false);
setIdealFootprint(targetHeapSize + overhead);
size_t freeBytes = getAllocLimit(hs);
if (freeBytes < CONCURRENT_MIN_FREE) {
/* Not enough free memory to allow a concurrent GC. */
heap->concurrentStartBytes = SIZE_MAX;
} else {
//For small footprint, we keep the min percentage to start
//concurrent GC; for big footprint, we keep the absolute value
//of free to start concurrent GC
heap->concurrentStartBytes = freeBytes - MIN(freeBytes * (float)(0.2), concurrentStart);
}
/* Mark that we need to run finalizers and update the native watermarks
* next time we attempt to register a native allocation.
*/
gHs->nativeNeedToRunFinalization = true;
}
static void markObjectNonNull(const Object *obj, GcMarkContext *ctx,
bool checkFinger)
{
assert(ctx != NULL);
assert(obj != NULL);
assert(dvmIsValidObject(obj));
if (obj < (Object *)ctx->immuneLimit) {
assert(isMarked(obj, ctx));
return;
}
//在heapbitmap里标记
//如果之前标记过会返回之前的标记值
if (!setAndReturnMarkBit(ctx, obj)) {
/* This object was not previously marked.
*/
//如果之前未出现过,压入栈
//将对象的字段对象压入栈,如果以前已经设过标记值,则不压入栈,避免死循环
if (checkFinger && (void *)obj < ctx->finger) {
/* This object will need to go on the mark stack.
*/
markStackPush(&ctx->stack, obj);
}
}
}
static unsigned long _heapBitmapModifyObjectBit(HeapBitmap *hb, const void *obj,
bool setBit, bool returnOld)
{
const uintptr_t offset = (uintptr_t)obj - hb->base;
//index与offset的关系?
const size_t index = HB_OFFSET_TO_INDEX(offset);
//mask的值与offset相关
const unsigned long mask = HB_OFFSET_TO_MASK(offset);
assert(hb->bits != NULL);
assert((uintptr_t)obj >= hb->base);
assert(index < hb->bitsLen / sizeof(*hb->bits));
if (setBit) {
if ((uintptr_t)obj > hb->max) {
hb->max = (uintptr_t)obj;
}
if (returnOld) {
unsigned long *p = hb->bits + index;
const unsigned long word = *p;
*p |= mask;
return word & mask;
} else {
hb->bits[index] |= mask;
}
} else {
hb->bits[index] &= ~mask;
}
return false;
}