.Net Core CLR 获取跟对象代码的分析

.Net Core CLR GC 的第一步过程就是标记阶段,其余的分别为,标记,计划,压缩,重定位,清扫。五个阶段。

首先来看下标记阶段,所谓的标记阶段,就是CLR 会标记存活的对象,以便于不被清扫掉,而造成程序异常。标记的第一步首先是要获取到跟对象,通过跟对象获取到正在使用的对象,然后进行一个标记,所有代码均为C++如下:

CLR的GC阶段的标记函数为:

void gc_heap::mark_phase (int condemned_gen_number, BOOL mark_only_p)
{
    
    
        GCScan::GcScanRoots(GCHeap::Promote,
                                condemned_gen_number, max_generation,
                                &sc);

}

注意看 这里面GCHeap::Promote就是获取到对象然后进行一个标记的过程

void GCHeap::Promote(Object** ppObject, ScanContext* sc, uint32_t flags)
{
    
    
    uint8_t* o = (uint8_t*)*ppObject;
    if (o == 0)
        return;
    gc_heap* hp = gc_heap::heap_of (o);
    dprintf (3, ("Promote %Ix", (size_t)o));
#ifdef INTERIOR_POINTERS
    if (flags & GC_CALL_INTERIOR)
    {
    
    
        if ((o < hp->gc_low) || (o >= hp->gc_high))
        {
    
    
            return;
        }
        if ( (o = hp->find_object (o, hp->gc_low)) == 0)
        {
    
    
            return;
        }
    }
    if ((o >= hp->gc_low) && (o < hp->gc_high))
    {
    
    
        hpt->mark_object_simple (&o THREAD_NUMBER_ARG);
    }
}

而GCScanRoots函数如下:

void GCToEEInterface::GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc)
{
    
    
   while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
    {
    
    
     
        if (GCHeapUtilities::GetGCHeap()->IsThreadUsingAllocationContextHeap(
            pThread->GetAllocContext(), sc->thread_number))
        {
    
    
            ScanStackRoots(pThread, fn, sc);
    }
}
static void ScanStackRoots(Thread * pThread, promote_func* fn, ScanContext* sc)
{
    
    
 pThread->StackWalkFrames( GcStackCrawlCallBack, &gcctx, flagsStackWalk);
}

可以看到 GCScanoots调用了StackWalkFrames函数,这个函数里面会循环初始化一些结构体填充,以获取到需要扫描的对象

StackWalkAction Thread::StackWalkFramesEx(
                    PREGDISPLAY pRD,        // virtual register set at crawl start
                    PSTACKWALKFRAMESCALLBACK pCallback,
                    VOID *pData,
                    unsigned flags,
                    PTR_Frame pStartFrame
                )
{
    
    
   StackFrameIterator iter;
        if (iter.Init(this, pStartFrame, pRD, flags) == TRUE)
        {
    
    
            while (iter.IsValid())
            {
    
    
                retVal = MakeStackwalkerCallback(&iter.m_crawl, pCallback, pData DEBUG_ARG(iter.m_uFramesProcessed));
                if (retVal == SWA_ABORT)
                {
    
    
                    break;
                }

                retVal = iter.Next();
                if (retVal == SWA_FAILED)
                {
    
    
                    break;
                }
            }
        }

}

然后循环标记

猜你喜欢

转载自blog.csdn.net/tangyanzhi1111/article/details/109148517
CLR