lua 5.2 GC 源码分析 一

来源:互联网 发布:linux系统可以做什么 编辑:程序博客网 时间:2024/05/16 23:51

      最近一直在看lua5.2的GC。总想写点自己的理解。
       今天也看的差不多了,可以开始写了。
       此前查阅了官方的一些资料,推荐给大家,下面是网址:
       http://lua-users.org/wiki/GarbageCollection

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

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. /* kinds of Garbage Collection */  
  2. #define KGC_NORMAL  0  
  3. #define KGC_EMERGENCY   1   /* gc was forced by an allocation failure */  
  4. #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主要参与变色,和弱表中的键与值的回收。

0 0
原创粉丝点击