GC2_ConcurrentCopying

ConcurrentCopying

virtual GcType GetGcType() const OVERRIDE {
    //ConcurrentCopying仅支持kGcTypePartial,也就是不扫描ImageSpace和
    //ZygoteSpace(除了那些有dirty card的对象)
    return kGcTypePartial;
}
virtual CollectorType GetCollectorType() const OVERRIDE {
    return kCollectorTypeCC;//返回回收器类型
}
void SetRegionSpace(space::RegionSpace* region_space) {
    //region_space_是ConcurrentCopying的成员变量
    //ConcurrentCopying要回收的垃圾对象就在这个region_space_中
    region_space_ = region_space;
}

RunPhases

void ConcurrentCopying::RunPhases() {
    is_active_ = true;
    Thread* self = Thread::Current();
    thread_running_gc_ = self;
    {
        ReaderMutexLock mu(self, *Locks::mutator_lock_);
        InitializePhase();//①初始化阶段
    }
    FlipThreadRoots();//②完成半空间Flip工作
    {
        ReaderMutexLock mu(self, *Locks::mutator_lock_);
        MarkingPhase();//③标记
    }
    ......
    {
        ReaderMutexLock mu(self, *Locks::mutator_lock_);
        ReclaimPhase();//④回收
    }
    FinishPhase();//收尾工作,非常简单,请读者自行阅读
    is_active_ = false;
    thread_running_gc_ = nullptr;
}

InitializePhase

void ConcurrentCopying::InitializePhase() {
    ......
    CheckEmptyMarkStack();//详情见下文代码分析
    //immune_spaces_类型为ImmuneSpace,保存了不需要GC的空间对象
    immune_spaces_.Reset();
    .....
    /*下面的代码逻辑将设置force_evacuate_all_成员变量,它和RegionSpace有关,我们
      后续用到该变量时再介绍其含义。*/
    if (GetCurrentIteration()->GetGcCause() == kGcCauseExplicit ||
        GetCurrentIteration()->GetGcCause() == kGcCauseForNativeAlloc ||
        GetCurrentIteration()->GetClearSoftReferences()) {
        force_evacuate_all_ = true;
    } else {
        force_evacuate_all_ = false;
    }
    BindBitmaps();//详解见下文代码分析
    ......
}

CheckEmptyMarkStack

void ConcurrentCopying::CheckEmptyMarkStack() {
    Thread* self = Thread::Current();
    /*Thread tlsPtr_中有一个名为thread_local_mark_stack的成员变量,其定义如下:
      AtomicStack<:Object>* thread_local_mark_stack;
      thread_local_mark_stack是专门配合ConcurrentCopying而使用的,其数据类型就是
      AtomicStack(和上文提到的Heap allocation_stack_、mark_stack_一样)
      tlsPtr_ thread_local_mark_stack的具体用法我们后文碰到时再介绍。
      MarkStackMode是枚举变量,其中定义了4个枚举值(它们的含义们下文碰到时再介绍):
      enum MarkStackMode {
          kMarkStackModeOff = 0, kMarkStackModeThreadLocal,
          kMarkStackModeShared, kMarkStackModeGcExclusive
      };
      mark_stack_mode_是ConcurrentCopying成员变量,初始值为kMarkStackModeOff。
      GC过程中将修改它。*/
    MarkStackMode mark_stack_mode = mark_stack_mode_.LoadRelaxed();
    //mark_stack_mode取值为kMarkStackModeThreadLocal的处理逻辑
    if (mark_stack_mode == kMarkStackModeThreadLocal) {
        /*RevokeThreadLocalMarkStack将要求各个Java Thread执行一个CheckPoint任务,
          该任务有三个关键处理,笔者列举如下:
        (1) 获取线程对象的tlsPtr_ thread_local_mark_stack对象(通过Thread
            GetThreadLocalMarkStack)。该对象初值为空,ConcurrentCopying GC过程中
            会设置它(详情见后文分析)。
        (2) 如果线程的thread_local_mark_stack不为空,则将它保存到ConcurrentCopying
            revoked_mark_stacks_(类型为vector<ObjectStack*>)成员变量中。
        (3) 调用Thread SetThreadLocalMarkStack,将thread_local_mark_stack设置为空。
        RevokeThreadLocalMarkStacks的调用结果就是将线程对象中不为空的
        thread_local_mark_stack放到revoked_mark_stacks_数组中。  */
        RevokeThreadLocalMarkStacks(false);
        MutexLock mu(Thread::Current(), mark_stack_lock_);
        //如果revoked_mark_stacks_不为空,则需要逐个清除其中所包含的Object对象
        if (!revoked_mark_stacks_.empty()) {
            for (accounting::AtomicStack<mirror::Object>* mark_stack : revoked_mark_stacks_) {
             while (!mark_stack->IsEmpty()) {
                    mirror::Object* obj = mark_stack->PopBack();
                    ......//打印信息
                }
            }
        }
    } else {//如果mark_stack_mode取值为其他值
        MutexLock mu(Thread::Current(), mark_stack_lock_);
        //gc_mark_stack_指向一个ObjectStack对象
        CHECK(gc_mark_stack_->IsEmpty());
        CHECK(revoked_mark_stacks_.empty());
    }
}

BindBitmaps

void ConcurrentCopying::BindBitmaps() {
    Thread* self = Thread::Current();
    WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
    for (const auto& space : heap_->GetContinuousSpaces()) {
        //ConcurrentCopying只支持kGcTypePartial,所以ImageSpace、ZygoteSpace
        //同样会被加到immune_spaces_中
        if (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyNeverCollect ||
                space->GetGcRetentionPolicy() == space::kGcRetentionPolicyFullCollect) {
            CHECK(space->IsZygoteSpace() || space->IsImageSpace());
            immune_spaces_.AddSpace(space);
            /*cc_heap_bitmap_类型为HeapBitmap,cc_bitamps_类型为
              vector< SpaceBitmap<kObjectAlignment>*>。这两个成员变量由
              ConcurrentCopying内部使用。*/
            const char* bitmap_name = space->IsImageSpace() ? "cc image space bitmap" :  "cc zygote space bitmap";
            accounting::ContinuousSpaceBitmap* bitmap =
                accounting::ContinuousSpaceBitmap::Create(bitmap_name,space->Begin(), space->Capacity());
            cc_heap_bitmap_->AddContinuousSpaceBitmap(bitmap);
            cc_bitmaps_.push_back(bitmap);
        } else if (space == region_space_) {
            accounting::ContinuousSpaceBitmap* bitmap =
                accounting::ContinuousSpaceBitmap::Create( "cc region space bitmap", 
                                      space->Begin(), space->Capacity());
            cc_heap_bitmap_->AddContinuousSpaceBitmap(bitmap);
            cc_bitmaps_.push_back(bitmap);
            region_space_bitmap_ = bitmap;
        }
    }
}

FlipThreadRoots

图解

graph LR
subgraph RootObject
GC线程-->交换From和To空间
Mutator线程-->VisitRoots("thread->VisitRoots")
end


VisitRoots-->|callback root ref|Mark("mirror::Object* to_ref = Mark(ref);")
Mark-->|forwarding address|GetFwdPtr
Mark-->Copy
Mark-->PushOntoMarkStack

subgraph ObjectReferencedByRoot
ProcessMarkStack-->|遍历mark_stack中的根对象得到to_ref|VisitReferences("to_ref->VisitReferences")
end


VisitReferences-->|得到field ref|Mark("mirror::Object* to_ref = Mark(ref)得到ref的to_ref,标记,拷贝")-->updateRef
void ConcurrentCopying::FlipThreadRoots() {
    ......
    Thread* self = Thread::Current();
    Locks::mutator_lock_->AssertNotHeld(self);
    gc_barrier_->Init(self, 0);
    ThreadFlipVisitor thread_flip_visitor(this, heap_->use_tlab_);
    FlipCallback flip_callback(this);
    heap_->ThreadFlipBegin(self);
    /*Runtime FlipThreadRoots将先暂停线程对象,然后设置它们的flip_function,
      接着再恢复它们的运行。FlipThreadRoots前两个参数分别是两个闭包对象,其中:
      (1) GC线程(也就是当前调用FlipThreadRoots的线程)先执行flip_callback。
      (2) 其他所有Java线程对象再执行thread_flip_visitor。
      根据ThreadList的注释,FlipThreadRoots只由ConcurrentCopying使用。 */
    size_t barrier_count = Runtime::Current()->FlipThreadRoots(&thread_flip_visitor, &flip_callback, this);
    heap_->ThreadFlipEnd(self);
    ......
    is_asserting_to_space_invariant_ = true;
    ......
}

FlipCallback

class FlipCallback : public Closure {
    public:
        ......
        virtual void Run(Thread* thread) OVERRIDE {
            ConcurrentCopying* cc = concurrent_copying_;
            ......
            Thread* self = Thread::Current();
            ......
            /*调用RegionSpace的SetFromSpace。rb_table_为ReadBarrierTable,来自Heap的成员
            变量rb_table_。ReadBarrieTable的启用需要设置前台回收器类型为
            kCollectorTypeCC,并且定义编译宏kUseTableLookupReadBarrier。*/
            cc->region_space_->SetFromSpace(cc->rb_table_,cc->force_evacuate_all_);
            //内部调用HeapSwapStacks。交换Heap allocation_stack_和live_stack_
            cc->SwapStacks();
            ......
            cc->is_marking_ = true;
            //设置mark_stack_mode_的值为kMarkStackModeThreadLocal
            cc->mark_stack_mode_.StoreRelaxed(ConcurrentCopying::kMarkStackModeThreadLocal);
            .......
    }
    ......
};

region_space.cc

RegionSpace::SetFromSpace
void RegionSpace::SetFromSpace(accounting::ReadBarrierTable* rb_table,
                bool force_evacuate_all) {
    /*回顾13.3.2节的内容可知,RegionSpace把内存资源划分成数个块,每一个块由一个Region对象
      描述。num_regions_是Region的个数,而region_数组保存了各个内存块对应的Region信息。*/
    ......
    for (size_t i = 0; i <num_regions_; ++i) {
        Region* r = &regions_[i];
        /*RegionState枚举变量描述了一个Region的状态,我们重点看前两个枚举值的含义:
          (1) kRegionStateFree:表示Region为空闲待使用状态
          (2) kRegionStateAllocated:表示Region已经有一部分内存被分配了。
          RegionType枚举变量描述了一个Region的类型,它有如下五种取值:
          (1) kRegionTypeAll:代码中没有明确使用它的地方,读者可不考虑
          (2) kRegionTypeFromSpace:Region位于From Space中,需要被清除(evacuate)
          (3) kRegionTypeUnevacFromSpace:该Region位于From Space,但是不需要被清除
          (4) kRegionTypeToSpace:Region位于To Space中。
          (5) kRegionTypeNone:Region的默认类型。
        如果一个Region首先被使用,其类型将从kRegionTypeNone转换为 kRegionTypeToSpace。相关代码见Region Unfree函数。  */
        RegionState state = r->State();
        RegionType type = r->Type();
        if (!r->IsFree()) {//IsFree返回false,说明该Region已经被使用
            if (LIKELY(num_expected_large_tails == 0U)) {
            /*ShouldBeEvacuated用于判断一个Region是否需要被清除。Region中有两个成员变量
              与之相关:
            (1) is_newly_allocated_:bool型。一个Region从kRegionStateFree到kRegion-
                StateAllocated时,该成员变量被设置为true(通过调用Region SetNewlyAllocated
                函数来完成)。如果is_newly_allocated_为true,ShouldBeEvacuated返回也为true。
            (2) live_bytes_:非垃圾对象所占内存的字节数。如果它和该Region中所分配的总内存字节数
                之比小于75%(kEvaculateLivePercentThreshold),则ShouldBeEvacuated也返
                回true。*/
          bool should_evacuate = force_evacuate_all || r->ShouldBeEvacuated();
          if (should_evacuate) {
             r->SetAsFromSpace();//设置Region的类型为kRegionTypeFromSpace
          } else {
             //设置Region的类型为kRegionTypeUnevacFromSpace
             r->SetAsUnevacFromSpace();
            }
            ........
            }.......
        } else {
            ......
        }
    }
    current_region_ = &full_region_;
    evac_region_ = &full_region_;
}

ThreadFlipVisitor

class ThreadFlipVisitor : public Closure {
    public:
    ......
    virtual void Run(Thread* thread) OVERRIDE {
        Thread* self = Thread::Current();
        //设置线程对象tls32_is_gc_marking为true
        thread->SetIsGcMarking(true);
        if (use_tlab_ && thread->HasTlab()) {
            if (ConcurrentCopying::kEnableFromSpaceAccountingCheck) {
                ......
            } else {
                //撤销RegionSpace为线程thread分配的TLAB
                concurrent_copying_->region_space_->RevokeThreadLocalBuffers(thread);
            }
        }
        if (kUseThreadLocalAllocationStack) {
            //撤销线程本地Allocation Stack
            thread->RevokeThreadLocalAllocationStack();
        }
        ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
        //访问线程根对象。ConcurrentCopying的VisitRoots函数将被调用,其内部调用
        //MarkRoot。我们下文将重点分析MarkRoot函数
        thread->VisitRoots(concurrent_copying_);
        concurrent_copying_->GetBarrier().Pass(self);
    }
    ......
};
// Process some roots.
inline void ConcurrentCopying::VisitRoots(
    mirror::Object*** roots, size_t count, const RootInfo& info ATTRIBUTE_UNUSED) {
  for (size_t i = 0; i < count; ++i) {
    mirror::Object** root = roots[i];
    mirror::Object* ref = *root;
    mirror::Object* to_ref = Mark(ref);
    ......
  }
}

inline void ConcurrentCopying::VisitRoots(
    mirror::CompressedReference<mirror::Object>** roots, size_t count,
    const RootInfo& info ATTRIBUTE_UNUSED) {
  for (size_t i = 0; i < count; ++i) {
    mirror::CompressedReference<mirror::Object>* const root = roots[i];
    if (!root->IsNull()) {
      // kGrayImmuneObject is true because this is used for the thread flip.
      MarkRoot</*kGrayImmuneObject*/true>(root);
    }
  }
}
inline void ConcurrentCopying::MarkRoot(CompressedReference<Object>* root) {
    //ref是当前正在被访问的某个线程根对象
    mirror::Object* const ref = root->AsMirrorPtr();
    /*调用ConcurrentCopying Mark,返回一个to_ref对象。to_ref的内容和ref一样,
      但它可能位于其他空间中(这就是拷贝的含义,详情见下文对Mark的分析)。
      如果to_ref和ref不相同,则需要修改存储ref的内存,使得它指向新的to_ref。
      具体的修改方式是先将root转换为一个Atomic<CompressedReference<Object>>*对象,
      然后进行原子操作。总之,在Mark函数后,原线程根对象可能被更新为位于另外一个空间中的对象。*/
    mirror::Object* to_ref = Mark(ref);
    if (to_ref != ref) {
        auto* addr = reinterpret_cast<Atomic<CompressedReference<Object>>*> (root);
        auto expected_ref = CompressedReference<Object>::FromMirrorPtr(ref);
        auto new_ref = CompressedReference<Object>::FromMirrorPtr(to_ref);
        do {
            if (ref != addr->LoadRelaxed().AsMirrorPtr()) {
        break;
        }
        } while (!addr->CompareExchangeWeakRelaxed(expected_ref, new_ref));
    }
}
ConcurrentCopying::Mark
inline mirror::Object* ConcurrentCopying::Mark(mirror::Object* from_ref) {
    ......
    //获取from_ref所在的Region的类型。注意,如果from_ref不是region_space_的对象,
    //则GetRegionType返回kRegionTypeNone
    space::RegionSpace::RegionType rtype = region_space_->GetRegionType(from_ref);
    switch (rtype) {
        case space::RegionSpace::RegionType::kRegionTypeToSpace:
            //如果from_ref已经在To Space中,则直接返回它。不需要后续的拷贝
            return from_ref;
        case space::RegionSpace::RegionType::kRegionTypeFromSpace: {
        /*如果from_ref位于From Space中(由Region ShouldEvacuate函数决定),则调用
            GetFwdPtr找到from_ref的拷贝对象。下文将介绍GetFwdPtr函数。main*/
            mirror::Object* to_ref = GetFwdPtr(from_ref);
        ......
        if (to_ref == nullptr) {
            //如果from_ref不存在对应的拷贝对象,则调用Copy生成一个拷贝对象
            to_ref = Copy(from_ref);
        }
            return to_ref;
        }
        case space::RegionSpace::RegionType::kRegionTypeUnevacFromSpace: {
            mirror::Object* to_ref = from_ref;
            //如果from_ref位于from space中不需要清理的Region的话,则对该对象进行标记
            if (region_space_bitmap_->AtomicTestAndSet(from_ref)) {
            } else {
            //如果from_ref是初次标记,则调用PushOntoMarkStack,下文将介绍该函数,main
            PushOntoMarkStack(to_ref);
            }
            return to_ref;
        }
        case space::RegionSpace::RegionType::kRegionTypeNone:
        /*如果Region类型为kRegionTypeNone,说明from_ref不是region_space_中的
          对象(有可能是ImageSpace或ZygoteSpace中的对象),则调用MarkNonMoving
          函数。这种情况下无须拷贝from_ref。但它的引用型成员变量所指向的对象可能被拷贝
          了,我们需要做对应的处理。读者不妨自行阅读MarkNonMoving函数。  */
        return MarkNonMoving(from_ref);
    default:
        UNREACHABLE();
    }
}
inline mirror::Object* ConcurrentCopying::GetFwdPtr( mirror::Object* from_ref) {
    //先拿到from_ref monitor_对应的LockWord对象
    LockWord lw = from_ref->GetLockWord(false);
    /*如果lw的状态为kForwardingAddress,说明lw包含了一个mirror Object对象的地址
      信息。对Copying Collection而言,这个地址就是from_ref对应的拷贝对象的地址,
      GC理论称之为Forwarding Address。*/
    if (lw.GetState() == LockWord::kForwardingAddress) {
        Object* fwd_ptr = reinterpret_cast<Object*>(lw.ForwardingAddress());
        return fwd_ptr; //fwd_ptr就是from_ref的拷贝对象
    } else {
        return nullptr;
    }
}
ConcurrentCopying::Copy
//Copy函数拷贝from_ref对象的信息到一个新的对象to_ref中,然后将to_ref的地址存储到from_ref monitor_成员变量中。在GC理论中,这个地址叫Forwading Address。
mirror::Object* ConcurrentCopying::Copy(mirror::Object* from_ref) {
    //获取from_ref对象的内存大小
    size_t obj_size = from_ref->SizeOf<...>();
    //按Region的要求进行对齐
    size_t region_space_alloc_size = RoundUp(obj_size, space::RegionSpace::kAlignment);
    ......
    //从region_space_中分配一块内存用来存储from_ref的内容。这块内存的起始地址为
    //to_ref
    mirror::Object* to_ref = region_space_->AllocNonvirtual<true>(....);
    ......//region_space_分配失败的处理,这部分逻辑比较复杂,读者可先不关注它
    while (true) {
        //拷贝:将from_ref的信息拷贝到to_ref
        memcpy(to_ref, from_ref, obj_size);
        /*下面这段代码比较复杂,但功能很简单,设置from_ref的monitor_,就是把to_ref的地址
          值设置到from_ref monitor_中。*/
        LockWord old_lock_word = to_ref->GetLockWord(false);
        ......
        //构造新的LockWord对象
        LockWord new_lock_word = LockWord::FromForwardingAddress(
                                reinterpret_cast<size_t>(to_ref));
        //原子操作,设置到from_ref里去。所以这段逻辑会比较复杂
        bool success = from_ref->CasLockWordWeakSequentiallyConsistent(
                                old_lock_word, new_lock_word);
        if (LIKELY(success)) {
            ......
            PushOntoMarkStack(to_ref);//保存to_ref
            return to_ref;
        }
        .....
    }
}
ConcurrentCopying::PushOntoMarkStack
void ConcurrentCopying::PushOntoMarkStack(mirror::Object* to_ref) {
    Thread* self = Thread::Current();
    MarkStackMode mark_stack_mode = mark_stack_mode_.LoadRelaxed();
    //在FlipCallback中,mark_stack_mode_已经设置为kMarkStackModeThreadLocal了
    if (LIKELY(mark_stack_mode == kMarkStackModeThreadLocal)) {
        if (LIKELY(self == thread_running_gc_)) {
            ......
        //根据上文的介绍可知,PushOntoMarkStack可能由不同的Java线程调用。如果
        //调用者是GC线程自己,则把to_ref加到ConcurrentCopying gc_mark_stack_中
        gc_mark_stack_->PushBack(to_ref);
        } else {
        /*如果是非GC线程调用PushOntoMarkStack,则需要使用线程对象tlsPtr_
          thread_local_mark_stack。注意,如果线程对象还没有这个容器或者它已经存满的话,下
          面的代码将从ConcurrentCopying pooled_mark_stacks_容器中取一个空闲的容器给线程。
          pooled_mark_stacks_是一个数组,保存了256个ObjectStack对象,每一个ObjectStack只
          能保存最多4096个Object指针。*/
        accounting::AtomicStack<mirror::Object>* tl_mark_stack = self->GetThreadLocalMarkStack();
        //tl_mark_stack不存在或者tl_mark_stack已满的情况
        if (UNLIKELY(tl_mark_stack == nullptr || tl_mark_stack->IsFull())) {
        MutexLock mu(self, mark_stack_lock_);
        accounting::AtomicStack<mirror::Object>* new_tl_mark_stack;
        if (!pooled_mark_stacks_.empty()) {
            new_tl_mark_stack = pooled_mark_stacks_.back();
            pooled_mark_stacks_.pop_back();
        } else {
            //如果pooled_mark_stacks_被用完,则新建一个ObjectStack
            new_tl_mark_stack =
                accounting::AtomicStack<mirror::Object>::Create(
                    "thread local mark stack", 4 * KB, 4 * KB);
        }
        new_tl_mark_stack->PushBack(to_ref);
        self->SetThreadLocalMarkStack(new_tl_mark_stack);
        if (tl_mark_stack != nullptr) {
            revoked_mark_stacks_.push_back(tl_mark_stack);
      }
        } else {
          tl_mark_stack->PushBack(to_ref);
        }
      }
    }
    /*mark_stack_mode取值为非kMarkStackModeThreadLocal的处理,也是将对象
    存储到ConcurrentCopying gc_mark_stack_中。*/
    ......
}

MarkingPhase

void ConcurrentCopying::MarkingPhase() {
    /*MarkingPhase调用前,我们只对线程根对象进行了Mark(注意,此处使用Mark这个词一方
      面代表它是ConcurrentCopying中的一个函数。另一方面,根据上文相关函数的代码分析可
      知,ConcurrentCopying中的Mark除了做标记之外,还会根据需要生成拷贝对象)。*/
    ......
    {
    ......
    /*扫描ImageSpace中的根对象。这里我们要多说几句。在MarkSweep中,对ImageSpace的扫描是
      基于Write Barrier以及CardTable的。但Write Barrier这种技术却不能用于会移动对象的垃圾
      回收算法。比如Copying collection。原因很简单,因为对象被移动后,它在card table中对
      应card的位置也会发生变化。所以,对Copying Collection来说,Read Barrier就派上了用
      场。Read Barrier有好几种比较经典的实现。ART中有三种,如TableLookup RB、Baker RB以
      及Brooks RB。
      笔者简单介绍下RB的大致作用:当mutator读取一个对象A的引用型成员变量a时,如果a所指向的对
      象B携有forwarding address(B的拷贝对象B'),则转去读取B'。因为B有了拷贝对象B',我们
      自然希望凡是读取B的地方都改成读取B'。*/
    for (space::ContinuousSpace* space : heap_->GetContinuousSpaces()) {
        if (space->IsImageSpace()) {
            gc::space::ImageSpace* image = space->AsImageSpace();
            if (image != nullptr) {
                mirror::ObjectArray<mirror::Object>* image_root =
                        image->GetImageHeader().GetImageRoots();
                    //ImageSpace中的根对象不会被拷贝,所以marked_image_root等于image_root,
                    //这段代码有些类似校验的作用
                    mirror::Object* marked_image_root = Mark(image_root);
                    ......//一些校验相关的工作
                }
            }
        }
    }
        {//访问其他类型的根对象
        ......
        Runtime::Current()->VisitConcurrentRoots(this, kVisitRootFlagAllRoots);
        }
        {//访问其他类型的根对象
        ......
        Runtime::Current()->VisitNonThreadRoots(this);
        }

    //访问immune_spaces_中的空间
    for (auto& space : immune_spaces_.GetSpaces()) {
        accounting::ContinuousSpaceBitmap* live_bitmap = space->GetLiveBitmap();
        /*ConcurrentCopyingImmuneSpaceObjVisitor内部将在cc_heap_bitmap_中对扫描到
          的对象进行标记,同时调用PushOntoMarkStack*/
        ConcurrentCopyingImmuneSpaceObjVisitor visitor(this);
        live_bitmap->VisitMarkedRange(
                    reinterpret_cast<uintptr_t>(space->Begin()),
                    reinterpret_cast<uintptr_t>(space->Limit()),
                    visitor);
    }
    /*到此,所有根对象(包括immune_space_中的对象)都进行了标记。并且,根对象如果发生了
      拷贝,则原始根对象将被替换为新的拷贝对象。接下来的工作就比较简单了,我们要遍历这些根
      对象,将它们所引用的对象进行Mark(标记、拷贝)。同时,我们还要更新引用值。*/
    Thread* self = Thread::Current();
    {/*下面这段代码中包含三次ProcessMarkStack,这和ConcurrentCopying中的mark_stack_
      mode_有关,它有四种取值。此次调用ProcessMarkStack时,mark_stack_mode_取值为
      kMarkStackModeThreadLocal。*/
        ProcessMarkStack();

        //切换mark_stack_mode_为kMarkStackModeShared

       SwitchToSharedMarkStackMode();
        ProcessMarkStack();

        //切换mark_stack_mode_为kMarkStackModeGcExclusive
        SwitchToGcExclusiveMarkStackMode();
        //对Java Reference对象的处理,各种回收器的处理都一样。我们后续统一介绍
        ProcessReferences(self);
        ......
        ProcessMarkStack();

        ......;
        Runtime::Current()->GetClassLinker()->CleanupClassLoaders();
        DisableMarking();
        ......
    }
    ......
}
//ProcessMarkStack内部将遍历通过PushOntoMarkStack保存下来的对象(这些对象都是拷贝后得到的对象,代码中用to_ref来表示)。其中最关键函数的是Scan。
inline void ConcurrentCopying::Scan(mirror::Object* to_ref) {
    //Scan很简单,就是遍历to_ref的引用型成员变量,内部调用ConcurrentCopying的Process函数进行处理。 */
    ConcurrentCopyingRefFieldsVisitor visitor(this);
    to_ref->VisitReferences<...>(visitor, visitor);
}
inline void ConcurrentCopying::Process(mirror::Object* obj, MemberOffset offset) {
    //obj是上面Scan中的to_ref,而offset是obj的某个引用型成员变量(由下面的ref表示)
    mirror::Object* ref = obj->GetFieldObject<....>(offset);
    //对ref进行Mark,得到ref的to_ref,如果两个一样,则不需要更新obj offset的内容
    mirror::Object* to_ref = Mark(ref);
    if (to_ref == ref) { return; }
    /*到此,更新obj offset的内容,使得它指向to_ref。由于使用的是原子操作,所以下面的
      代码逻辑中会使用循环。*/
    mirror::Object* expected_ref = ref;
    mirror::Object* new_ref = to_ref;
    do {
        if (expected_ref != obj->GetFieldObject<......>(offset)) {
            break;
        }
    } while (!obj->CasFieldWeakRelaxedObjectWithoutWriteBarrier<...>(
                offset, expected_ref, new_ref));
}

ReclaimPhase

图解

graph LR
Clear("region_space_->ClearFromSpace()")
Sweep过程和MarkSweepl类似
void ConcurrentCopying::ReclaimPhase() {
    ......
    {
        .....
        ComputeUnevacFromSpaceLiveRatio();//详情见下文代码分析
    }
    {
        .....
        region_space_->ClearFromSpace();//详情见下文代码分析
    }

    {
        WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
        ......
         /*清空除immune_spaces_、region_space_外的空间中其他的垃圾对象。代码逻辑和
          MarkSweep Sweep的类似。内部调用ContinuousMemMapAllocSpace的Sweep函数进
          行处理。*/
    Sweep(false);
    //调用GarbageCollector的SwapBitmaps函数,和MarkSweep的处理一样
    SwapBitmaps();
    heap_->UnBindBitmaps();
    ......
}
void ConcurrentCopying::ComputeUnevacFromSpaceLiveRatio() {
    ......
    //对RegionSpace中的标记对象进行统计
    ConcurrentCopyingComputeUnevacFromSpaceLiveRatioVisitor visitor(this);
    region_space_bitmap_->VisitMarkedRange(
                    reinterpret_cast<uintptr_t>(region_space_->Begin()),
                    reinterpret_cast<uintptr_t>(region_space_->Limit()),
                                        visitor);
}