[toc]
# 概述
这系列文章会一步步的拆解 Lua 的实现原理,直到到达 Lua Wrap 与 Lua 本身的数据交互为止
# 宏孩儿实现 GC 对象判定
首先讨论一个问题,在 c 语言里,我们如何判断一个对象是否可 GC?
有 N 种方法吧,这里来讨论下
1. C 没有模板,所以没法 traits,C++ 可以 traits 撸几个特性模板
2. 写一大堆 if
3. 宏孩儿 这是从 Lua 源码中读来的,其实也是 C 语言实现面向对象的一种很棒的实践
下面均是从第 3 条出发,以 Lua 对象为例,步步引出 Lua 的默认对象 Lua 的一个基础类型是 Table
,这个类型的原型如下:
1 | typedef struct Table { |
其中 GCObject 和 CommonHeader 的标志如下:
1 | /* |
注释部分说的很明显了,所有可以 GC 的对象都包含 CommonHeader,GCObject 是 CommonHeader 的一个特化,其中农 tt
是用来标志类型的变量 Table 中的元素是各种类型变量,其对象原型如下:
1 |
|
可以发现 TValue 的最后一个值中存放了一个 lu_byte tt_
后面就是通过这个值来判定是否可以 GC 的,如下 (下面是 5.4 的,5.1 的 leisi 类似):
1 | /* Bit mark for collectable types */ |
这里开始就开始出现宏的骚操作了
Lua 内部定义了一个 BIT_ISCOLLECTABLE
来表示某变量当第六位为 1 时则表示是可 GC 的
然后定义了 iscollectable(O)
宏用来判定是否是可 GC 对象,这里就是第一个宏孩儿的骚操作点: 通过 rawtt(o)
把压力交给编译器
除非你的对象里有 tt_
,否则编译是不会被通过的。 然后下面还有一个获取 gcvalue 的宏 gcvalue(o)
,这个宏后面有一个 iscollectable(o)
,这个意思就是如果不是 gc 对象,编译器甚至不会通过,把压力全部交给编译器
# Lua 基础对象
上面已经说了一部分继承关系了,下面这张图是《Lua 设计与实现》这本书里的继承图示,在最新的 Lua5.4 中,这层继承关系已经变了, GCheader
已经被干掉了,图上的 GCObject 实际上是 GCUnion
这里还是以 5.1.5 为例