kvm垃圾收集-006

本文介紹kvm中垃圾收集中的sweep.sweep的意思是: 將垃圾對象清除(其實垃圾區域的對象還是存在的,但是由於沒有對象引用,同時之後在分配對象時,會在這些區域分配,分配時會進行清零操作.因此,也就表現爲實際清除了一樣)。此處的代碼如下:

static CHUNK
sweepTheHeap(long *maximumFreeSizeP)
{
    CHUNK firstFreeChunk = NULL;
    CHUNK newChunk;
    CHUNK* nextChunkPtr = &firstFreeChunk;
    bool_t done = FALSE;

    cell* scanner =  CurrentHeap; /* current object */
    cell* endScanPoint = CurrentHeapEnd;
    long maximumFreeSize = 0;
    long thisFreeSize;
    do {
        /* Skip over groups of live objects 1. 跳過存活的對象 */
        cell *lastLive;
        while (scanner < endScanPoint && ISKEPT(*scanner)) {
            *scanner &= ~MARKBIT; // 將標記位置0
            scanner += SIZE(*scanner) + HEADERSIZE;
        }
        lastLive = scanner;
        /* Skip over all the subsequent dead objects 2. 跳過所有的垃圾對象*/
        while (scanner < endScanPoint && !ISKEPT(*scanner)) {
#if INCLUDEDEBUGCODE
            if (tracememoryallocation && (TYPE(*scanner) != GCT_FREE)) {
                Log->freeObject((long)scanner,
                    (INSTANCE_CLASS)((OBJECT)(scanner + HEADERSIZE))->ofClass,
                    (long)SIZE(*scanner) + HEADERSIZE);
            }
#endif /* INCLUDEDEBUGCODE */
            scanner += SIZE(*scanner) + HEADERSIZE;
        }
        if (scanner == endScanPoint) {
            if (scanner == lastLive) {
                /* The memory ended precisely with a live object. 此時的情況是 內存中都是存活對象 */
                break;
            } else {
                done = TRUE;
            }
        }
        // 計算free 的大小
        thisFreeSize = (scanner - lastLive - 1);
        newChunk = (CHUNK)lastLive;
        newChunk->size = thisFreeSize << TYPEBITS;

        *nextChunkPtr = newChunk;
        nextChunkPtr = &newChunk->next;
        if (thisFreeSize > maximumFreeSize) {
            maximumFreeSize = thisFreeSize;
        }
    } while (!done);

    *nextChunkPtr = NULL;
    *maximumFreeSizeP = maximumFreeSize;
    return firstFreeChunk;
}

此處的代碼比較簡單.將垃圾對象所在的區域當做free 區.同時構建成free鏈表.另外此處還將存活對象的標記位置爲0(以備下次gc時使用).

當sweep後,代碼回到garbageCollectForReal方法.其代碼如下:

 firstFreeChunk = sweepTheHeap(&maximumFreeSize);
#if ENABLE_HEAP_COMPACTION
    if (realSize > maximumFreeSize) {// 當heap 內最大的可用內存不滿足要求時,需要進行壓縮處理
        /* We need to compact the heap. */
        breakTableStruct currentTable;
        // 壓縮
        cell* freeStart = compactTheHeap(&currentTable, firstFreeChunk);
        if (currentTable.length > 0) {
        	// 修改指針
            updateRootObjects(&currentTable);
            updateHeapObjects(&currentTable, freeStart);
        }
        
        // 壓縮後,重新計算free 的大小.整理後, free 只有一塊.
        if (freeStart < CurrentHeapEnd - 1) {
            firstFreeChunk = (CHUNK)freeStart;
            firstFreeChunk->size =
                (CurrentHeapEnd - freeStart - HEADERSIZE) << TYPEBITS;
            firstFreeChunk->next = NULL;
        } else {
            /* 
             * 沒有空閒內存
             */
            firstFreeChunk = NULL;
        }
    }
#endif
    FirstFreeChunk = firstFreeChunk;

此時,如果sweep後最大的free chunk的大小不滿足要求(realSize).則需要進行壓縮.也就是將活動對象移動到一端.同時在移動的過程中要更新對象的引用(因爲對象的位置變了)。同時, free chunk也就只有一個了(壓縮的本來含義).

關於壓縮的compactTheHeap, updateRootObjects等方法我們後續文章介紹…(這幾個方法還是比較複雜的,就不在這裏展開了)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章