heap gc1

void dvmCollectGarbageInternal(const GcSpec* spec)

{

    GcHeap *gcHeap = gDvm.gcHeap;

    u4 gcEnd = 0;

    u4 rootStart = 0 , rootEnd = 0;

    u4 dirtyStart = 0, dirtyEnd = 0;

    size_t numObjectsFreed, numBytesFreed;

    size_t currAllocated, currFootprint;

    size_t percentFree;

    int oldThreadPriority = INT_MAX;

 

    /* The heap lock must be held.

     */

 

    if (gcHeap->gcRunning) {

        LOGW_HEAP("Attempted recursive GC");

        return;

    }

 

    // Trace the beginning of the top-level GC.

    if (spec == GC_FOR_MALLOC) {

        ATRACE_BEGIN("GC (alloc)");

    } else if (spec == GC_CONCURRENT) {

        ATRACE_BEGIN("GC (concurrent)");

    } else if (spec == GC_EXPLICIT) {

        ATRACE_BEGIN("GC (explicit)");

    } else if (spec == GC_BEFORE_OOM) {

        ATRACE_BEGIN("GC (before OOM)");

    } else {

        ATRACE_BEGIN("GC (unknown)");

    }

 

    gcHeap->gcRunning = true;

 

    rootStart = dvmGetRelativeTimeMsec();

    ATRACE_BEGIN("GC: Threads Suspended"); // Suspend A

    dvmSuspendAllThreads(SUSPEND_FOR_GC);

 

    /*

     * If we are not marking concurrently raise the priority of the

     * thread performing the garbage collection.

     */

    if (!spec->isConcurrent) {

        oldThreadPriority = os_raiseThreadPriority();

    }

    if (gDvm.preVerify) {

        LOGV_HEAP("Verifying roots and heap before GC");

        verifyRootsAndHeap();

    }

 

    dvmMethodTraceGCBegin();

 

    /* Set up the marking context.

     */

    if (!dvmHeapBeginMarkStep(spec->isPartial)) {

        ATRACE_END(); // Suspend A

        ATRACE_END(); // Top-level GC

        LOGE_HEAP("dvmHeapBeginMarkStep failed; aborting");

        dvmAbort();

    }

 

    /* Mark the set of objects that are strongly reachable from the roots.

     */

    LOGD_HEAP("Marking...");

                //设置根节点,强可达类型

    dvmHeapMarkRootSet();

 

    /* dvmHeapScanMarkedObjects() will build the lists of known

     * instances of the Reference classes.

     */

    assert(gcHeap->softReferences == NULL);

    assert(gcHeap->weakReferences == NULL);

    assert(gcHeap->finalizerReferences == NULL);

    assert(gcHeap->phantomReferences == NULL);

    assert(gcHeap->clearedReferences == NULL);

 

    if (spec->isConcurrent) {

        /*

         * Resume threads while tracing from the roots.  We unlock the

         * heap to allow mutator threads to allocate from free space.

         */

        dvmClearCardTable();

        dvmUnlockHeap();

        dvmResumeAllThreads(SUSPEND_FOR_GC);

        ATRACE_END(); // Suspend A

        rootEnd = dvmGetRelativeTimeMsec();

    }

 

    /* Recursively mark any objects that marked objects point to strongly.

     * If we're not collecting soft references, soft-reachable

     * objects will also be marked.

     */

    LOGD_HEAP("Recursing...");

                //递归所有对象

    dvmHeapScanMarkedObjects();

 

    if (spec->isConcurrent) {

        /*

         * Re-acquire the heap lock and perform the final thread

         * suspension.

         */

        dirtyStart = dvmGetRelativeTimeMsec();

        dvmLockHeap();

        ATRACE_BEGIN("GC: Threads Suspended"); // Suspend B

        dvmSuspendAllThreads(SUSPEND_FOR_GC);

        /*

         * As no barrier intercepts root updates, we conservatively

         * assume all roots may be gray and re-mark them.

         */

        dvmHeapReMarkRootSet();

        /*

         * With the exception of reference objects and weak interned

         * strings, all gray objects should now be on dirty cards.

         */

        if (gDvm.verifyCardTable) {

            dvmVerifyCardTable();

        }

        /*

         * Recursively mark gray objects pointed to by the roots or by

         * heap objects dirtied during the concurrent mark.

         */

        dvmHeapReScanMarkedObjects();

    }

 

    /*

     * All strongly-reachable objects have now been marked.  Process

     * weakly-reachable objects discovered while tracing.

     */

    dvmHeapProcessReferences(&gcHeap->softReferences,

                             spec->doPreserve == false,

                             &gcHeap->weakReferences,

                             &gcHeap->finalizerReferences,

                             &gcHeap->phantomReferences);

 

#if defined(WITH_JIT)

    /*

     * Patching a chaining cell is very cheap as it only updates 4 words. It's

     * the overhead of stopping all threads and synchronizing the I/D cache

     * that makes it expensive.

     *

     * Therefore we batch those work orders in a queue and go through them

     * when threads are suspended for GC.

     */

    dvmCompilerPerformSafePointChecks();

#endif

 

    LOGD_HEAP("Sweeping...");

 

    dvmHeapSweepSystemWeaks();

 

    /*

     * Live objects have a bit set in the mark bitmap, swap the mark

     * and live bitmaps.  The sweep can proceed concurrently viewing

     * the new live bitmap as the old mark bitmap, and vice versa.

     */

    dvmHeapSourceSwapBitmaps();

 

    if (gDvm.postVerify) {

        LOGV_HEAP("Verifying roots and heap after GC");

        verifyRootsAndHeap();

    }

 

    if (spec->isConcurrent) {

        dvmUnlockHeap();

        dvmResumeAllThreads(SUSPEND_FOR_GC);

        ATRACE_END(); // Suspend B

        dirtyEnd = dvmGetRelativeTimeMsec();

    }

    dvmHeapSweepUnmarkedObjects(spec->isPartial, spec->isConcurrent,

                                &numObjectsFreed, &numBytesFreed);

    LOGD_HEAP("Cleaning up...");

    dvmHeapFinishMarkStep();

    if (spec->isConcurrent) {

        dvmLockHeap();

    }

 

    LOGD_HEAP("Done.");

    /* Now's a good time to adjust the heap size, since

     * we know what our utilization is.

     *

     * This doesn't actually resize any memory;

     * it just lets the heap grow more when necessary.

     */

    //调整heap的大小

    dvmHeapSourceGrowForUtilization();

 

    currAllocated = dvmHeapSourceGetValue(HS_BYTES_ALLOCATED, NULL, 0);

    currFootprint = dvmHeapSourceGetValue(HS_FOOTPRINT, NULL, 0);

 

    dvmMethodTraceGCEnd();

    LOGV_HEAP("GC finished");

 

    gcHeap->gcRunning = false;

 

    LOGV_HEAP("Resuming threads");

    /*

     * Move queue of pending references back into Java.

     */

    dvmEnqueueClearedReferences(&gDvm.gcHeap->clearedReferences);

 

    gcEnd = dvmGetRelativeTimeMsec();

    percentFree = 100 - (size_t)(100.0f * (float)currAllocated / currFootprint);

    if (!spec->isConcurrent) {

        u4 markSweepTime = dirtyEnd - rootStart;

        u4 gcTime = gcEnd - rootStart;

        bool isSmall = numBytesFreed > 0 && numBytesFreed < 1024;

#if ENABLE_STAT_GC

        // for gc_for_alloc

        accumulateGcStat(3, markSweepTime, numBytesFreed);       

#endif

        ALOGD("%s freed %s%zdK, %d%% free %zdK/%zdK, paused %ums, total %ums",

             spec->reason,

             isSmall ? "<" : "",

             numBytesFreed ? MAX(numBytesFreed / 1024, 1) : 0,

             percentFree,

             currAllocated / 1024, currFootprint / 1024,

             markSweepTime, gcTime);

    } else {

        u4 rootTime = rootEnd - rootStart;

        u4 dirtyTime = dirtyEnd - dirtyStart;

        u4 gcTime = gcEnd - rootStart;

        bool isSmall = numBytesFreed > 0 && numBytesFreed < 1024;

        ALOGD("%s freed %s%zdK, %d%% free %zdK/%zdK, paused %ums+%ums, total %ums",

             spec->reason,

             isSmall ? "<" : "",

             numBytesFreed ? MAX(numBytesFreed / 1024, 1) : 0,

             percentFree,

             currAllocated / 1024, currFootprint / 1024,

             rootTime, dirtyTime, gcTime);

    }

    if (gcHeap->ddmHpifWhen != 0) {

        LOGD_HEAP("Sending VM heap info to DDM");

        dvmDdmSendHeapInfo(gcHeap->ddmHpifWhen, false);

    }

    if (gcHeap->ddmHpsgWhen != 0) {

        LOGD_HEAP("Dumping VM heap to DDM");

        dvmDdmSendHeapSegments(false, false);

    }

    if (gcHeap->ddmNhsgWhen != 0) {

        LOGD_HEAP("Dumping native heap to DDM");

        dvmDdmSendHeapSegments(false, true);

    }

 

    ATRACE_END(); // Top-level GC

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值