1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
|
/*
** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $
** Global State
** See Copyright Notice in lua.h
*/
#ifndef lstate_h
#define lstate_h
#include "lua.h"
#include "lobject.h"
#include "ltm.h"
#include "lzio.h"
struct lua_longjmp; /* defined in ldo.c */
/* table of globals */
#define gt(L) (&L->l_gt)
/* registry */
#define registry(L) (&G(L)->l_registry)
/* extra stack space to handle TM calls and some other extras */
#define EXTRA_STACK 5
#define BASIC_CI_SIZE 8
#define BASIC_STACK_SIZE (2*LUA_MINSTACK)
//c 散列桶
//c 全局存放字符串的地方。如果一个字符串在此存在,不用重新生成。
//c 如果表扩张的太厉害,每个桶的字符串太多,会进行一次rehash,重新分配每个桶的数据量
//c rehash在lstring.c -> luaS_resize
typedef struct stringtable {
GCObject **hash; //c 字符串,因为是散列桶,所以是**
lu_int32 nuse; //c 桶用到的容量,因为不一定size都用到了 /* number of elements */
int size; //c 桶的总容量,是常值
//c nuse和size是用来动态控制桶容量的关键
} stringtable;
//c 当前函数的调用信息,和lua_State的调用部分类似
//c 都有top, base俩个与栈相关的成员
//c StkId引用的永远是lua_State栈上的内容
/*
** informations about a call
*/
typedef struct CallInfo {
//c 当前调用的base值,即在栈上操作的开始位置
StkId base; /* base for this function */
//c 函数原型在lua_State数据栈上的位置
StkId func; /* function index in the stack */
//c 此函数调用过程中的top指针
StkId top; /* top for this function */
//c 当前执行到的指令位置
const Instruction *savedpc;
//c 期待的返回值个数
int nresults; /* expected number of results from this function */
//c 尾调用个数
int tailcalls; /* number of tail calls lost under this entry */
} CallInfo;
#define curr_func(L) (clvalue(L->ci->func))
#define ci_func(ci) (clvalue((ci)->func))
#define f_isLua(ci) (!ci_func(ci)->c.isC)
#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci))
//c 当前虚拟机所有协程共用的内容
/*
** `global state', shared by all threads of this state
*/
typedef struct global_State {
//c string table,开散列表,存储所有的字符串
stringtable strt; /* hash table for strings */
lua_Alloc frealloc; /* function to reallocate memory */
void *ud; /* auxiliary data to `frealloc' */
//region 与GC相关
lu_byte currentwhite;//当前的白色类型,用于lgc.h>luaC_white()
// 当前的GC状态,有5个,在lgc.h定义
lu_byte gcstate; /* state of garbage collector */
// strt中字符串散列桶索引,字符串回收阶段每次回收一个散列桶的字符串,记录对应的散列桶索引
int sweepstrgc; /* position of sweep in `strt' */
// 所有新建的对象都会暂存在这里,在GC的清理阶段会增量地遍历整个链表。新建对象会加在最*前面*,见luaC_link()
GCObject *rootgc; /* list of all collectable objects */
// 保存rootgc中当前回收到的位置,下次从这个位置继续回收
GCObject **sweepgc; /* position of sweep in `rootgc' */
// 灰色链表
GCObject *gray; /* list of gray objects */
// 需要一次性扫描处理的,不可被打断的对象的灰色链表,比如LUA_THREAD
GCObject *grayagain; /* list of objects to be traversed atomically */
// 弱表
GCObject *weak; /* list of weak tables (to be cleared) */
// 有__gc方法的userdata,会在GC阶段调用__gc释放native侧的引用。指向链表最后一个
GCObject *tmudata; /* last element of list of userdata to be GC */ // taggedmethodudata带__gc的udata
//endregion 与GC有关
//region 与内存管理有关的
Mbuffer buff; /* temporary buffer for string concatentation */
// GC开始的阈值,
lu_mem GCthreshold;
// 开始进行GC的阈值,当超过这个值时开始GC
lu_mem totalbytes; /* number of bytes currently allocated */
// 当前使用的内存大小的估计值
lu_mem estimate; /* an estimate of number of bytes actually in use */
// 待回收的内存大小
lu_mem gcdept; /* how much GC is `behind schedule' */
// 一个百分数,控制下一轮GC开始时机,越大,离下次gc开始的时间越长
int gcpause; /* size of pause between successive GCs */
// 控制GC回收速度\gc的粒度
int gcstepmul; /* GC `granularity' */
//endregion 与内存管理有关的
lua_CFunction panic; /* to be called in unprotected errors */
TValue l_registry; //全局唯一的注册表,所有lua_State共享一个
struct lua_State *mainthread; // 主线程对象,不会被回收
UpVal uvhead; /* head of double-linked list of all open upvalues */
// 基本类型的元方法
struct Table *mt[NUM_TAGS]; /* metatables for basic types */
TString *tmname[TM_N]; /* array with tag-method names */
} global_State;
//c StkId引用的永远是lua_State栈上的内容,准确来说是base+bias
/*
** `per thread' state
*/
struct lua_State {
CommonHeader;
lu_byte status;
//c 当前栈的下一个可用位置
StkId top; /* first free slot in the stack */
//c 当前函数栈的基地址,给某个函数用,在luad_precall函数中设置L->base = ci->base = ci->func + 1;
//c 每个方法被调用时都会得到自己的一组虚拟“寄存器”,也就是栈上面的数据
StkId base; /* base of current function */
global_State *l_G;
//c 当前执行中函数的调用信息,是base_ci数组中的某个
CallInfo *ci; /* call info for current function */
//c 当前执行到的指令位置。为了处理函数的调用和恢复,会在luaD_precall和luaD_poscall设置和恢复
const Instruction *savedpc; /* `savedpc' of current function */
//c lua_State数据栈的终点
StkId stack_last; /* last free slot in the stack */
//c 数据栈(栈数组的起始地址)(数据栈的起始点)
StkId stack; /* stack base */
//c callinfo数组的终点
CallInfo *end_ci; /* points after end of ci array*/
//c callinfo 数组, 沿着base_ci遍历可以得到完整的lua调用链
CallInfo *base_ci; /* array of CallInfo's */
int stacksize;
int size_ci; /* size of array `base_ci' */
unsigned short nCcalls; /* number of nested C calls */
unsigned short baseCcalls; /* nested C calls when resuming coroutine */
lu_byte hookmask;
lu_byte allowhook;
int basehookcount;
int hookcount;
lua_Hook hook;
TValue l_gt; /* table of globals */ //全局表 _G global table
TValue env; /* temporary place for environments */ // 协程私有的环境
GCObject *openupval; /* list of open upvalues in this stack */
GCObject *gclist;
struct lua_longjmp *errorJmp; /* current error recover point */
ptrdiff_t errfunc; /* current error handling function (stack index) */
};
#define G(L) (L->l_G)
//c 需要GC的类型基类,通过GCObject能够引用到GCheader中定义的/
//c #define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
//c 这种写法是一种实现C继承的方式
//c 每个
/*
** Union of all collectable objects
*/
union GCObject {
GCheader gch;
union TString ts;
union Udata u;
union Closure cl;
struct Table h;
struct Proto p;
struct UpVal uv;
struct lua_State th; /* thread */
};
//c TValue\GCObject 获取union中的内容
/* macros to convert a GCObject into a specific value */
#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))
#define gco2ts(o) (&rawgco2ts(o)->tsv)
#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
#define gco2u(o) (&rawgco2u(o)->uv)
#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
#define ngcotouv(o) \
check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv))
#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
/* macro to convert any Lua object into a GCObject */
#define obj2gco(v) (cast(GCObject *, (v)))
LUAI_FUNC lua_State *luaE_newthread (lua_State *L);
LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
#endif
|