关于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' */
}
mark开头的接口,在判断该节点为白色之后,会将该节点插入g->gray链表的头部。
在remarkupvals接口中,在判断uv节点为灰色之后,会将uv->v值放到染色逻辑中,过滤。
propagateall接口过滤当前g->gray链表。
retraversegrays重新遍历所有灰色节点的链表(把traverse翻译成遍历就很好理解了)。
convergeephemerons过滤g->ephemeron链表。
separatetobefnz从g->finobj链表上将无法到达的节点移动到g->tobefnz链表上。
g->currentwhite = cast_byte(otherwhite(g));切换白色比特位,这样以后,下次再遇到是白色,并且与当前白色不同的节点,就是可以回收的对象了。