最近Lua 5.4 work1已经发布了, 其中GC最大的变化就是增加了分代GC的实现, 而GC在动态语言中一向是重中之重. 趁着这个机会, 我打算具体比较一下Lua5.3和Lua5.4中GC实现到底是如何变迁的, 根据以往的经验来看, 这其中必然充满各种精巧的设计.
Lua5.3的GC源码以前就断断续续看过一次了, 这次打算从头再分析一遍, 并做一下笔记为分析Lua5.4 GC做准备.
在Lua中字符串、表、用户数据、函数、线程、 内部结构等对象,都使用GC模块进行管理.
在分析GC流程前先做一些准备工作, 比如lua中的Value是如何实现的.
//lobject.h /* ** Common type for all collectable objects */ typedef struct GCObject GCObject; /* ** Common Header for all collectable objects (in macro form, to be ** included in other objects) */ #define CommonHeader GCObject *next; lu_byte tt; lu_byte marked /* ** Common type has only the common header */ struct GCObject { CommonHeader; }; /* ** Union of all Lua values */ typedef union Value { GCObject *gc; /* collectable objects */ void *p; /* light userdata */ int b; /* booleans */ lua_CFunction f; /* light C functions */ lua_Integer i; /* integer numbers */ lua_Number n; /* float numbers */ } Value; #define TValuefields Value value_; int tt_ typedef struct lua_TValue { TValuefields; } TValue;
在编写的lua代码中,全部是以TValue来表示的,而这个TValue到底是哪种类型是靠tt_字段来标识的.
tt_字段中的bits0-3用来表示基础类型可选值如下.
//lua.h #define LUA_TNIL 0 #define LUA_TBOOLEAN 1 #define LUA_TLIGHTUSERDATA 2 #define LUA_TNUMBER 3 #define LUA_TSTRING 4 #define LUA_TTABLE 5 #define LUA_TFUNCTION 6 #define LUA_TUSERDATA 7 #define LUA_TTHREAD 8
一些基础类型中可能会有不同的变种,tt_字段的bits4-5用来表示每个基础类型中更具体的子类型, 在lobject.h中定义如下:
/* ** LUA_TFUNCTION variants: ** 0 - Lua function ** 1 - light C function ** 2 - regular C function (closure) */ /* Variant tags for functions */ #define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */ #define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */ #define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */ /* Variant tags for strings */ #define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */ #define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */ /* Variant tags for numbers */ #define LUA_TNUMFLT (LUA_TNUMBER | (0 << 4)) /* float numbers */ #define LUA_TNUMINT (LUA_TNUMBER | (1 << 4)) /* integer numbers */
tt_字段的bit6中来表示此value是否可回收, 其中宏定义同样在lobject.h中定义
/* Bit mark for collectable types */ #define BIT_ISCOLLECTABLE (1 << 6)
在lobject.h中提供了一组宏用于获取tt_字段中的各种含义
#define val_(o) ((o)->value_) /* raw type tag of a TValue */ #define rttype(o) ((o)->tt_) /* tag with no variants (bits 0-3) */ #define novariant(x) ((x) & 0x0F) /* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ #define ttype(o) (rttype(o) & 0x3F) /* type tag of a TValue with no variants (bits 0-3) */ #define ttnov(o) (novariant(rttype(o)))
其中CommonHeader中的tt字段与TValue中的tt_字段的bits0-5是一致的.
《Lua5.3 GC源码阅读(1)》有1条评论