kvm垃圾收集-002

本文我们来介绍kvm中的垃圾收集器的实现.其算法为mark-and-sweep(含有压缩功能).其方法为garbageCollect.代码如下:

void
garbageCollect(int moreMemory)
{
#if INCLUDEDEBUGCODE
    int beforeCollection = 0;
    int afterCollection = 0;
#endif

    // 1. 如果gcInProgress 不等于0,就意味着当前正在gc中,如果循环调用gc是不允许的
    if (gcInProgress != 0) {
        
        fatalVMError(KVM_MSG_CIRCULAR_GC_INVOCATION);
    }

    // 修改gc标记位
    gcInProgress++;

    // 2. 等待异步线程执行完毕
    RundownAsynchronousFunctions();

    if (ENABLEPROFILING && INCLUDEDEBUGCODE) {
        checkHeap();
    }
#if INCLUDEDEBUGCODE
    if ((tracegarbagecollection || tracegarbagecollectionverbose)
        && !TERSE_MESSAGES) {
            Log->startGC();
    }
#endif

#if INCLUDEDEBUGCODE
    if (ENABLEPROFILING || tracegarbagecollection
        || tracegarbagecollectionverbose) {

        beforeCollection = memoryFree();
    }
#endif

    MonitorCache = NULL;        /* Clear any temporary monitors */

    // 3. 在gc前 保存执行环境
    if (CurrentThread) {
        storeExecutionEnvironment(CurrentThread);
    }

    // 4. 执行gc
    garbageCollectForReal(moreMemory);

    // 5. 在gc执行后,恢复执行环境
    if (CurrentThread) {
        loadExecutionEnvironment(CurrentThread);
    }

#if INCLUDEDEBUGCODE
    if (ENABLEPROFILING || tracegarbagecollection
        || tracegarbagecollectionverbose) {

        afterCollection = memoryFree();

#if ENABLEPROFILING
        GarbageCollectionCounter += 1;
        DynamicDeallocationCounter += (afterCollection - beforeCollection);
#endif

        if (tracegarbagecollection || tracegarbagecollectionverbose) {

            Log->endGC(afterCollection - beforeCollection, afterCollection, getHeapSize());
        }
    }
#endif /* INCLUDEDEBUGCODE */

    // 6. 重新启动异步线程
    RestartAsynchronousFunctions();
    
    // 7. 重置gc标记位
    gcInProgress = 0;
}

其中参数为垃圾收集后所期望的可用内存大小.

步骤如下:

  1. 如果gcInProgress 不等于0,就意味着当前正在gc中,如果循环调用gc是不允许的.并修改gc标记位.
  2. 等待异步线程执行完毕
  3. 在gc前 保存执行环境
  4. 执行gc,关于此处,下文介绍
  5. 在gc执行后,恢复执行环境
  6. 重新启动异步线程
  7. 重置gc标记位

其中第二步代码如下:

void RundownAsynchronousFunctions(void) {

    for (;;) {

        if (collectorIsRunning) {
            fatalError(KVM_MSG_COLLECTOR_RUNNING_IN_RUNDOWNASYNCHRONOUSFUNCTIONS);
        }

        START_CRITICAL_SECTION
            if (AsyncThreadCount == 0) {
                collectorIsRunning = TRUE;
            }
        END_CRITICAL_SECTION

        if (collectorIsRunning) {
            break;
        }

        /* Wait */
        Yield_md();
    }

}

通过循环等待异步线程执行完毕.其中START_CRITICAL_SECTION, END_CRITICAL_SECTION为宏.定义如下:

void enterSystemCriticalSection(void);
void exitSystemCriticalSection(void);
#define START_CRITICAL_SECTION { enterSystemCriticalSection();
#define END_CRITICAL_SECTION   exitSystemCriticalSection(); }

可见,此处是线程锁.关于这点,可以参考如下链接:

线程锁的概念函数EnterCriticalSection和LeaveCriticalSection的用法


在gc前保存执行环境的代码如下:

void storeExecutionEnvironment(THREAD thisThread)
{
    // 将当前线程的执行环境(vm 所使用的寄存器)保存到THREAD中
    thisThread->fpStore = getFP();
    thisThread->spStore = getSP();
    thisThread->ipStore = getIP();
}

与之所对应的就是恢复执行环境,其代码如下:

void loadExecutionEnvironment(THREAD thisThread)
{
    // 恢复线程执行环境
    setFP(thisThread->fpStore);
    setLP(FRAMELOCALS(getFP()));
    setCP(getFP()->thisMethod->ofClass->constPool);
    setSP(thisThread->spStore);
    setIP(thisThread->ipStore);
}

重新启动异步线程的代码如下:

void RestartAsynchronousFunctions(void) {
    if (!collectorIsRunning) {
        fatalError(KVM_MSG_COLLECTOR_NOT_RUNNING_ON_ENTRY_TO_RESTARTASYNCHRONOUSFUNCTIONS);
    }
    collectorIsRunning = FALSE;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章