关于GC部分,更具体的涉及四个接口。
分别查看一下四个接口:
1、GCTM
GCTM是调用节点的元方法中的GC接口释放相应的虚拟机以外的内存。
2、freeobj
freeobj是释放proto、closure、upvalue、table、thread、userdata、string对象在分配的内存。
3、clearkeys
clearkeys则是清除lua弱表中hash部分的键对象,因为只有hash部分才有键值对关系。
4、clearvalues
clearvalues则是清除lua弱表中数组部分和hash部分的值对象(lua表分数组部分和hash部分)。
看完这些,大概可以更仔细的阅读接口atomic了。
- static l_mem atomic (lua_State *L) {
- global_State *g = G(L);
- l_mem work = -cast(l_mem, g->GCmemtrav); /* start counting work */
- GCObject *origweak, *origall;
- lua_assert(!iswhite(obj2gco(g->mainthread)));
- markobject(g, L); /* mark running thread */
- /* registry and global metatables may be changed by API */
- markvalue(g, &g->l_registry);
- markmt(g); /* mark basic metatables */
- /* remark occasional upvalues of (maybe) dead threads */
- remarkupvals(g);
- propagateall(g); /* propagate changes */
- work += g->GCmemtrav; /* stop counting (do not (re)count grays) */
- /* traverse objects caught by write barrier and by 'remarkupvals' */
- retraversegrays(g);
- work -= g->GCmemtrav; /* restart counting */
- convergeephemerons(g);
- /* at this point, all strongly accessible objects are marked. */
- /* clear values from weak tables, before checking finalizers */
- clearvalues(g, g->weak, NULL);
- clearvalues(g, g->allweak, NULL);
- origweak = g->weak; origall = g->allweak;
- work += g->GCmemtrav; /* stop counting (objects being finalized) */
- separatetobefnz(L, 0); /* separate objects to be finalized */
- markbeingfnz(g); /* mark objects that will be finalized */
- propagateall(g); /* remark, to propagate `preserveness' */
- work -= g->GCmemtrav; /* restart counting */
- convergeephemerons(g);
- /* at this point, all resurrected objects are marked. */
- /* remove dead objects from weak tables */
- clearkeys(g, g->ephemeron, NULL); /* clear keys from all ephemeron tables */
- clearkeys(g, g->allweak, NULL); /* clear keys from all allweak tables */
- /* clear values from resurrected weak tables */
- clearvalues(g, g->weak, origweak);
- clearvalues(g, g->allweak, origall);
- g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
- work += g->GCmemtrav; /* complete counting */
- return work; /* estimate of memory marked by 'atomic' */
- }
在remarkupvals接口中,在判断uv节点为灰色之后,会将uv->v值放到染色逻辑中,过滤。
propagateall接口过滤当前g->gray链表。
retraversegrays重新遍历所有灰色节点的链表(把traverse翻译成遍历就很好理解了)。
convergeephemerons过滤g->ephemeron链表。
separatetobefnz从g->finobj链表上将无法到达的节点移动到g->tobefnz链表上。
g->currentwhite = cast_byte(otherwhite(g));切换白色比特位,这样以后,下次再遇到是白色,并且与当前白色不同的节点,就是可以回收的对象了。