您的位置:首页 > 编程语言 > Lua

lua 5.2 GC 源码分析 一

2015-12-09 16:28 519 查看
最近一直在看lua5.2的GC。总想写点自己的理解。

今天也看的差不多了,可以开始写了。

此前查阅了官方的一些资料,推荐给大家,下面是网址:

http://lua-users.org/wiki/GarbageCollection

lua5.2里面有三种回收机制

[cpp] view
plaincopyprint?





/* kinds of Garbage Collection */

#define KGC_NORMAL 0

#define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */

#define KGC_GEN 2 /* generational collection */

1、普通模式

2、紧急模式

3、分代模式

可以通过接口lua_gc(what=LUA_GCGEN)设置当前模式为分代回收模式,不过作者在文档中说明,分代模式为实验版本,开发人员应当根据需求决定是否采用分代回收模式。

本文主要讲解普通回收机制。

lua回收遵循trace-mark-sweep算法。通过节点mainthread、L、l_registry出发追踪(trace)到任何可以到达的(reachable)节点,并将节点的颜色标记为灰色,或者为黑色。在trace-mark结束后,虚拟机中所有的节点只包含两种颜色,一种是白色,一种是黑色。而后在清扫(sweep)过程中,虚拟机中仍然为白色的节点会被回收。为黑色的节点表示是能够到达的节点。到达意味着被引用,该类节点不会被回收。

总结一下:通过跟踪、标记,清理,这三个过程,回收虚拟机中仍然为白色的节点,达到垃圾回收的目的。

虚拟机回收的起点是luaC_fullgc,在该接口中,主要涉及了以下五个接口:

1、sweeplist

2、callallpendingfinalizers

3、entersweep

4、luaC_runtilstate

5、singlestep

分别解释一下五个接口中都在做什么:

1、sweeplist

主要的用途是移除死亡的节点,回收该死亡节点的资源。节点死亡的条件是,当该节点为白色,并且与虚拟机当前的白色不同。这里要说明一下,lua中用了两个位来表示白色,每次trace-mark完之后,会切换一下虚拟机当前白色的比特位,具体代码在atomic接口中。在执行sweeplist时,若节点未死亡,则该节点的颜色会被染为当前的白色。

2、callallpendingfinalizers

该接口用来回收tobefnz链表上的节点。

3、entersweep

该接口通过调用sweeplist接口,回收finobj链表和allgc链表上的节点。

4、luaC_runtilstate

每次调用singlestep,实现单步回收,直到出现某个状态时停止回收。

5、singlestep

在该接口中主要调用了singlestep接口。在singlestep中,有五个分支,每个分支在执行完毕之后都会置状态值为下一个分支的状态,保证每个singlestep都会有序的执行,达到分步回收节点资源。其一般执行顺序为: GCSsweepstring==>GCSsweepudata==>GCSsweep==>GCSpause==>GCSpropagate==>GCSatomic==>GCSsweepstring。

在singlestep中比较重要的一个分支是GCSpropagate,在这里面调用了atomic接口和entersweep接口,entersweep上文已经说过,此处不再重复。说说atomic的作用,在atomic里面实现了trace-mark的原子过程,即,判断所有能到达的节点,并将其标记为黑色,而后切换当前虚拟机中的白色。这样一来,就不用担心在trace时某些节点的颜色值会发生变化。需要说明的是,虚拟机回收中,当前所有的链表都是单向的。在回收过程中,有两个需要注意的属性一个是CommonHeader中的next指针,一个是gclist指针。这两个指针都会负责将自己挂到不同的链表中,参与回收和变色。next主要参与回收,gclist主要参与变色,和弱表中的键与值的回收。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: