Skip to content

关于垃圾回收

Cthulhu edited this page Apr 16, 2018 · 2 revisions

安全点

垃圾回收只有在所有线程到达安全点时才会进行。 现在的安全点全部位于CodeExecution::invoke*()方法末尾

垃圾回收

垃圾回收器使用标记清除算法(未来可能支持其它..)。 markAndSweep()首先stop the world,防止有新引用产生/消失。 接下来:

future<void> stackMarkFuture, localMarkFuture;
    for(auto frame = frames.cbegin();frame!=frames.cend();++frame) {
        stackMarkFuture = gcThreadPool.submit([this,frame]()->void {
            for (auto stackSlot = (*frame)->stack.cbegin(); stackSlot != (*frame)->stack.cend(); ++stackSlot) {
                this->mark(*stackSlot);
            }
        });
        
        localMarkFuture = gcThreadPool.submit([this, frame]()->void {
            for (auto localSlot = (*frame)->locals.cbegin(); localSlot != (*frame)->locals.cend(); ++localSlot) {
                this->mark(*localSlot);
            }
        });

    }
    future<void> staticFieldsFuture = gcThreadPool.submit([this]()->void{
        for(auto c: yrt.ma->classTable) {
            std::for_each(c.second->sfield.cbegin(), c.second->sfield.cend(),
                [this](const pair<size_t, JType*>& offset){
                    if(typeid(*offset.second)==typeid(JObject)) {
                        objectBitmap.insert(offset.first);
                    }else if(typeid(*offset.second)==typeid(JArray)) {
                        arrayBitmap.insert(offset.first);
                    }
            });
        }
    });

提交三个并发mark()任务,第一个第二个任务代表GC root之一:调用栈(包括native 栈),第三个任务包括另一个:类静态字段 接下来垃圾回收线程阻塞,直到标记任务全部完成:

    staticFieldsFuture.get();
    if(!frames.empty()) {
        stackMarkFuture.get();
        localMarkFuture.get();
    }

sweep()表示清除阶段,他会清除未被标记的对象,数组,monitor。注意这里由于设计原因,对象内置锁由一个独立的map表示,所以也需要清理他。

void ConcurrentGC::sweep(){
    future<void> objectFuture = gcThreadPool.submit([this]()->void{
        for (auto pos = yrt.jheap->objheap.begin(); pos != yrt.jheap->objheap.end();) {
            // If we can not find active object in object bitmap then clear it
            // Notice that here we don't need to lock objectBitmap since it must 
            // be marked before sweeping
            if (objectBitmap.find(pos->first) == objectBitmap.cend()) {
                yrt.jheap->objheap.erase(pos++);
            }
            else {
                ++pos;
            }
        }
    });

    future<void> arrayFuture = gcThreadPool.submit([this]()->void {
        for (auto pos = yrt.jheap->arrheap.begin(); pos != yrt.jheap->arrheap.end();) {
            // DITTO
            if (arrayBitmap.find(pos->first) == arrayBitmap.cend()) {
                for (size_t i = 0; i < pos->second.first; i++) {
                    delete pos->second.second[i];
                }
                delete[] pos->second.second;
                yrt.jheap->arrheap.erase(pos++);
            }
            else {
                ++pos;
            }
        }
    });

    future<void> monitorFuture = gcThreadPool.submit([this]()->void {
        // DITTO
        for (auto pos = yrt.jheap->monitorheap.begin(); pos != yrt.jheap->monitorheap.end();) {
            if (objectBitmap.find(pos->first) == objectBitmap.cend() || arrayBitmap.find(pos->first) == arrayBitmap.cend()) {
                yrt.jheap->monitorheap.erase(pos++);
            }
            else {
                ++pos;
            }
        }
    });
}

清除阶段完成后,重置位图,然后resume the world

    objectFuture.get();
    arrayFuture.get();
    monitorFuture.get();
    resumeTheWorld();
Clone this wiki locally